Changes since last time:
- removed "WHERE IS NOT NULL" from lookup indexes
- some cleanups
- JSONB

## QA Timing

master branch b15fa552e288bec5bbc2b07a3e11bab9235a1e7c

    time ./fatcat_import.py import-issn /srv/datasets/journal_extra_metadata.csv # --batch-size 100
    real    0m30.249s
    user    0m9.364s
    sys     0m0.268s

    time parallel --bar --pipepart -j8 -a /srv/datasets/public_profiles_1_2_json.all.json ./fatcat_import.py import-orcid - # --batch-size 100
    => something went sort of wrong? seemed to hang, with no activity.
    => may have sent a signal or something accidentally?

    xzcat /srv/datasets/crossref-works.2018-01-21.json.xz | time parallel -j20 --round-robin --pipe ./fatcat_import.py import-crossref - /srv/datasets/20180216.ISSN-to-ISSN-L.txt --batch-size 100
    => ran for a few seconds before restarting with increased batch size
    => increased batch size seems to be too much for releases? stick with 50
    => still lots of long autovacuum (ANALYZE)

    67017.73user 2054.96system 25:59:38elapsed 73%CPU (0avgtext+0avgdata 424692maxresident)k
    2085872inputs+219678920outputs (100457major+30837042minor)pagefaults 0swaps
    # 25:59:38 elapsed

    time ./fatcat_import.py import-manifest /srv/datasets/idents_files_urls.sqlite # --batch-size 100
    => taking longer to start than I remembered...

    Done! Inserted 6607075
    real    1521m37.856s
    user    305m38.444s
    sys     18m13.916s
    => 25.5 hours

Disk/table usage:

    Size:  233.95G

                              table_name                          | table_size | indexes_size | total_size 
    --------------------------------------------------------------+------------+--------------+------------
     "public"."release_ref"                                       | 92 GB      | 26 GB        | 118 GB
     "public"."release_rev"                                       | 30 GB      | 14 GB        | 45 GB
     "public"."release_contrib"                                   | 12 GB      | 13 GB        | 26 GB
     "public"."release_edit"                                      | 4710 MB    | 3353 MB      | 8062 MB
     "public"."work_edit"                                         | 4710 MB    | 3352 MB      | 8062 MB
     "public"."work_ident"                                        | 3454 MB    | 4153 MB      | 7608 MB
     "public"."release_ident"                                     | 3454 MB    | 4152 MB      | 7606 MB
     "public"."work_rev"                                          | 2241 MB    | 2076 MB      | 4317 MB
     "public"."file_rev_url"                                      | 1994 MB    | 778 MB       | 2772 MB
     "public"."file_rev"                                          | 827 MB     | 1215 MB      | 2042 MB
     "public"."file_ident"                                        | 501 MB     | 533 MB       | 1034 MB
     "public"."file_edit"                                         | 590 MB     | 411 MB       | 1001 MB
     "public"."creator_rev"                                       | 371 MB     | 455 MB       | 826 MB
     "public"."abstracts"                                         | 649 MB     | 52 MB        | 701 MB
     "public"."file_release"                                      | 251 MB     | 435 MB       | 686 MB
     "public"."creator_edit"                                      | 347 MB     | 242 MB       | 590 MB
     "public"."creator_ident"                                     | 255 MB     | 305 MB       | 560 MB
     "public"."release_rev_abstract"                              | 70 MB      | 90 MB        | 160 MB
     "public"."changelog"                                         | 52 MB      | 53 MB        | 106 MB
     "public"."editgroup"                                         | 60 MB      | 35 MB        | 94 MB
     "public"."container_rev"                                     | 40 MB      | 27 MB        | 67 MB
     "public"."container_edit"                                    | 24 MB      | 16 MB        | 39 MB
     "public"."container_ident"                                   | 17 MB      | 20 MB        | 37 MB

I think this is before the JSONB schema change, so won't reflect actual/final.

Perf:

           relname        | too_much_seq | case |  rel_size   | seq_scan | idx_scan  
    ----------------------+--------------+------+-------------+----------+-----------
     file_rev_url         |          -18 | OK   |  2089836544 |        2 |        20
     file_release         |        -4001 | OK   |   263249920 |        2 |      4003
     container_edit       |      -132140 | OK   |    24608768 |        2 |    132142
     release_edit         |      -132140 | OK   |  4937408512 |        2 |    132142
     work_edit            |      -132140 | OK   |  4937351168 |        2 |    132142
     file_edit            |      -132140 | OK   |   618545152 |        2 |    132142
     creator_edit         |      -132140 | OK   |   363954176 |        2 |    132142
     changelog            |      -134456 | OK   |    54919168 |        5 |    134461
     container_rev        |     -1276670 | OK   |    41680896 |   592993 |   1869663
     abstracts            |     -1353093 | OK   |   669425664 |        3 |   1353096
     release_ref          |     -3429019 | OK   | 99223470080 |        3 |   3429022
     release_contrib      |     -3429026 | OK   | 13406437376 |        3 |   3429029
     release_rev_abstract |     -3435251 | OK   |    73359360 |        3 |   3435254
     creator_ident        |     -5360858 | OK   |   266977280 |       11 |   5360869
     creator_rev          |     -8071846 | OK   |   388734976 |   257781 |   8329627
     file_ident           |    -13478348 | OK   |   524746752 |        7 |  13478355
     file_rev             |    -30368193 | OK   |   867401728 |        4 |  30368197
     container_ident      |    -47140767 | OK   |    18219008 |        9 |  47140776
     release_ident        |    -61021070 | OK   |  3620864000 |       24 |  61021094
     work_rev             |   -106056502 | OK   |  2349146112 |        1 | 106056503
     work_ident           |   -106320780 | OK   |  3620954112 |        6 | 106320786
     editgroup            |   -117742455 | OK   |    62398464 |        2 | 117742457
     release_rev          |   -563415274 | OK   | 32455860224 |        8 | 563415282

Thought I had resoled those scans... hrm. Pretty sure (but not 100%) that I
cleared the counters.

Dumps!

    time psql fatcat_prod < ../extra/quick_dump.sql
    real    4m5.729s
    user    0m0.056s
    sys     0m0.016s
    => while other stuff running

    time ./ident_table_snapshot.sh
    => seems very dominated by tar/xz compression time; should switch back to gzip

    DATABASE_URL=$DATABASE_URL time ./ident_table_snapshot.sh /tmp
    614.80user 31.74system 13:23.51elapsed 80%CPU (0avgtext+0avgdata 10124maxresident)k
    8311456inputs+9761200outputs (2major+3792minor)pagefaults 0swaps
    => 13.5 minutes
    => fatcat_idents.2018-09-13.215147.r874951.tar.gz: 4.7GB
    => uncompressed, 8.3GB total

    cat ../extra/sql_dumps/fatcat_ident_releases.tsv | time ./target/release/fatcat-export release -j8 -q | pv -l | gzip > fatcat_release_dump.json.gz
    => can not run with more than -j8, it seems (postgres client limit)
    => TPS: 12522 (!)
    => 101k 0:00:34 [2.99k/s]
    => estimate 6.5 hours

    cat ../extra/sql_dumps/fatcat_ident_releases.tsv | time ./target/release/fatcat-export release --expand files,contaner -j8 -q | pv -l | gzip > fatcat_release_dump_expanded.json.gz
    => TPS: 29605 (!)
    => 183k 0:00:35 [ 5.8k/s] (how is this faster than the above? other disk stuff finished?)
    => 341k 0:01:07 [3.48k/s] (ah, must have been in disk cache)
    => 4.12M 0:16:11 (averaging 4.2k/s; estimate 4 hours total)
    => fatcat_release_dump_expanded.json.gz: 3.4G with 6.76M lines, so expecting 35GB or so

    ----total-cpu-usage---- -dsk/total- -net/total- ---paging-- ---system--
    usr sys idl wai hiq siq| read  writ| recv  send|  in   out | int   csw 
     14   3  73   8   0   2|  43M   21M| 143k  326B|   0     0 |  64k  113k
     18   4  72   5   0   2|  55M 4096k| 246k  326B|   0     0 |  84k  157k
     17   4  72   6   0   2|  53M 9964k| 428k  908B|   0     0 |  84k  155k
     14   3  73   8   0   1|  46M   20M| 143k   87k|   0     0 |  71k  132k
     18   3  72   5   0   2|  52M 8880k| 318k   95k|   0     0 |  82k  149k

    => fatcat-export using about 200% CPU in a single thread; other 8 threads at about 25% each
        => might be interesting to profile... too many copies? switch to tsv library?
    => seems like postgres only about 50% utilized

Benchmarks!

    # stub entity
    $ wrk -t8 -c100 -d30s http://localhost:9411/v0/work/aaaaaaaaaaaaavkvaaaaaaaaai
    Running 30s test @ http://localhost:9411/v0/work/aaaaaaaaaaaaavkvaaaaaaaaai
      8 threads and 100 connections
      Thread Stats   Avg      Stdev     Max   +/- Stdev
        Latency     7.44ms    5.26ms  67.53ms   60.07%
        Req/Sec     1.71k   113.55     2.07k    68.79%
      408986 requests in 30.01s, 117.01MB read
    Requests/sec:  13627.62
    Transfer/sec:      3.90MB
    => TPS: 39958
    => lots of "BEGIN" and "SELECT 1", implying new connections? hrm.
    => should run longer for more stable results

    wrk -t12 -c400 -d2m --latency http://localhost:9411/v0/work/aaaaaaaaaaaaavkvaaaaaaaaai

    Running 2m test @ http://localhost:9411/v0/work/aaaaaaaaaaaaavkvaaaaaaaaai
      12 threads and 400 connections
      Thread Stats   Avg      Stdev     Max   +/- Stdev
        Latency    25.75ms   17.02ms 263.74ms   65.11%
        Req/Sec     1.05k   377.38     1.82k    74.81%
      Latency Distribution
         50%   25.40ms
         75%   26.56ms
         90%   49.57ms
         99%   76.47ms
      1128253 requests in 2.00m, 322.80MB read
      Socket errors: connect 0, read 10, write 0, timeout 0
    Requests/sec:   9396.03
    Transfer/sec:      2.69MB

    => single 470% fatcatd thread; diesel?
    => 50% systemd-journald

    # rich entity
    $ wrk -t8 -c100 -d30s https://api.qa.fatcat.wiki/v0/release/aaaaaaaaaaaaarceaaaaaaaaam?expand=files,container
    Running 30s test @ https://api.qa.fatcat.wiki/v0/release/aaaaaaaaaaaaarceaaaaaaaaam?expand=files,container
      8 threads and 100 connections
      Thread Stats   Avg      Stdev     Max   +/- Stdev
        Latency    33.35ms   14.01ms 152.05ms   79.98%
        Req/Sec   363.14     30.36   464.00     76.48%
      86719 requests in 30.04s, 234.46MB read
    Requests/sec:   2886.55
    Transfer/sec:      7.80MB

    wrk -t12 -c400 -d2m --latency https://api.qa.fatcat.wiki/v0/release/aaaaaaaaaaaaarceaaaaaaaaam?expand=files,container

    Running 2m test @ https://api.qa.fatcat.wiki/v0/release/aaaaaaaaaaaaarceaaaaaaaaam?expand=files,container
      12 threads and 400 connections
      Thread Stats   Avg      Stdev     Max   +/- Stdev
        Latency   149.19ms  125.30ms   1.93s    95.06%
        Req/Sec   237.89     34.60   650.00     73.54%
      Latency Distribution
         50%  129.86ms
         75%  134.14ms
         90%  210.42ms
         99%  904.26ms
      340625 requests in 2.00m, 0.90GB read
      Socket errors: connect 0, read 0, write 0, timeout 303
    Requests/sec:   2836.17
    Transfer/sec:      7.67MB

    => TPS: 9090
    ----total-cpu-usage---- -dsk/total- -net/total- ---paging-- ---system--
     usr sys idl wai hiq siq| read  writ| recv  send|  in   out | int   csw 
      4   0  93   3   0   0|2401k   13M|   0     0 |2317B 4812B|4274  3824 
     22   6  68   0   0   3|4096B    0 |  57k  956B|4096B    0 | 135k  255k
     21   7  68   0   0   3|4096B    0 |  61k   66B|4096B    0 | 137k  259k
     21   7  68   0   0   3|  16k 8192B| 179k  636B|  16k    0 | 134k  252k
     21   7  68   0   0   3|   0     0 |  53k   66B|   0     0 | 135k  255k
     22   6  68   0   0   3|   0    17M|  51k  326B|   0     0 | 137k  261k
     22   6  68   0   0   3|   0     0 |  82k  903B|   0     0 | 136k  257k

    # static (404)
    wrk -t12 -c400 -d2m --latency http://localhost:9411/v0/asdf
    => full 2600+% CPU in a single fatcat process (?)
    => lots of load in wrk also
    => system at a whole basically 100% CPU on all cores, though mostly kernel

    ----total-cpu-usage---- -dsk/total- -net/total- ---paging-- ---system--
    usr sys idl wai hiq siq| read  writ| recv  send|  in   out | int   csw 
      4   0  93   3   0   0|2399k   13M|   0     0 |2315B 4808B|4359  3976 
     26  66   2   0   0   6|   0     0 |4191k  956B|   0     0 | 465k  536k
     26  67   1   0   0   6|   0     0 | 511k   66B|   0     0 | 466k  543k
     27  64   3   0   0   6|   0     0 |2648k  318B|   0     0 | 481k  555k
     25  67   2   0   0   6|   0     0 |1909k  768B|   0     0 | 481k  550k

    Running 2m test @ http://localhost:9411/v0/asdf
      12 threads and 400 connections
      Thread Stats   Avg      Stdev     Max   +/- Stdev
        Latency     1.40ms    1.65ms 219.48ms   93.33%
        Req/Sec    17.71k     8.97k   65.69k    63.84%
      Latency Distribution
         50%    1.13ms
         75%    1.89ms
         90%    2.71ms
         99%    4.76ms
      21145472 requests in 2.00m, 1.61GB read
      Socket errors: connect 0, read 12, write 0, timeout 0
      Non-2xx or 3xx responses: 21145472
    Requests/sec: 176071.79
    Transfer/sec:     13.77MB

Noting pretty non-trival traffic to 207.241.229.230 and
es-worker-02.us.archive.org (207.241.229.246)... probably because this is a
datanode?

## Misc

Postgres really wanted to log: <https://wiki.postgresql.org/wiki/Per-user_log_settings>

    ALTER DATABASE fatcat_prod SET log_statement = 'ddl';
    ALTER USER fatcat SET log_statement = 'ddl';


## Later Imports

    zcat /srv/datasets/2018-08-27-2352.17-matchcrossref.insertable.json.gz | pv -l | time parallel -j12 --round-robin --pipe ./fatcat_import.py import-matched -
    => only ~40 TPS
    => looks like almost all selects... probably skipping? huge postgres CPU churn, huh. missing index?

           relname        | too_much_seq |      case      |  rel_size   | seq_scan | idx_scan 
    ----------------------+--------------+----------------+-------------+----------+----------
     file_rev             |     -5343173 | OK             |   867483648 |      693 |  5343866

    EXPLAIN SELECT "file_ident"."id", "file_ident"."is_live", "file_ident"."rev_id", "file_ident"."redirect_id", "file_rev"."id", "file_rev"."extra_json", "file_rev"."size", "file_rev"."sha1", "file_rev"."sha256", "file_rev"."md5", "file_rev"."mimetype" FROM ("file_ident" INNER JOIN "file_rev" ON "file_ident"."rev_id" = "file_rev"."id") WHERE "file_rev"."sha1" = '7d97e98f8af710c7e7fe703abc8f639e0ee507c4' AND "file_rev"."sha1" IS NOT NULL AND "file_ident"."is_live" = 't' AND "file_ident"."redirect_id" IS NULL LIMIT 1;

Ugh, this whole cycle again. Query only takes 1ms for a no-hit, or 5ms for success.

    http get http://localhost:9411/v0/file/lookup?sha1=d77cb2a8b207507e0df27ba1393e8118eec9217f => not found
    http get http://localhost:9411/v0/file/lookup?sha1=d6c3f6ca785ee63293da02615c8495c5cd25fa25 => found
        => but no releases?

SET auto_explain.log_min_duration = 0;
SET auto_explain.log_analyze = true;
ALTER USER fatcat SET log_statement = 'all';
ALTER USER fatcat SET auto_explain.log_min_duration = 0;
ALTER USER fatcat SET auto_explain.log_analyze = true;;
sudo service fatcat-api restart


2018-09-16 00:42:29.883 UTC [13868] fatcat@fatcat_prod LOG:  duration: 3028.143 ms  plan:
        Query Text: SELECT "file_ident"."id", "file_ident"."is_live", "file_ident"."rev_id", "file_ident"."redirect_id", "file_rev"."id", "file_rev"."extra_json", "file_rev"."size", "file_rev"."sha1", "file_rev"."sha256", "file_rev"."md5", "file_rev"."mimetype" FROM ("file_ident" INNER JOIN "file_rev" ON "file_ident"."rev_id" = "file_rev"."id") WHERE "file_rev"."sha1" = $1 AND "file_rev"."sha1" IS NOT NULL AND "file_ident"."is_live" = $2 AND "file_ident"."redirect_id" IS NULL LIMIT $3
        Limit  (cost=0.43..8.56 rows=1 width=454) (actual time=3028.139..3028.139 rows=0 loops=1)
          ->  Nested Loop  (cost=0.43..268756.48 rows=33056 width=454) (actual time=3028.138..3028.138 rows=0 loops=1)
                ->  Seq Scan on file_rev  (cost=0.00..205023.16 rows=33042 width=405) (actual time=3028.137..3028.137 rows=0 loops=1)
                      Filter: ((sha1 IS NOT NULL) AND ((sha1)::text = 'd68d4e2cc420647109cdfe410efed86cd64465e5'::text))
                      Rows Removed by Filter: 6607786
                ->  Index Scan using file_ident_rev_idx on file_ident  (cost=0.43..1.92 rows=1 width=49) (never executed)
                      Index Cond: (rev_id = file_rev.id)
                      Filter: (is_live AND (redirect_id IS NULL))


fatcat_prod=# EXPLAIN SELECT "file_ident"."id", "file_ident"."is_live", "file_ident"."rev_id", "file_ident"."redirect_id", "file_rev"."id", "file_rev"."extra_json", "file_rev"."size", "file_rev"."sha1", "file_rev"."sha256", "file_rev"."md5", "file_rev"."mimetype" FROM ("file_ident" INNER JOIN "file_rev" ON "file_ident"."rev_id" = "file_rev"."id") WHERE "file_rev"."sha1" = '3f242a192acc258bdfdb15194341943222222222222440c313' AND "file_rev"."sha1" IS NOT NULL AND "file_ident"."is_live" = 't' AND "file_ident"."redirect_id" IS NULL LIMIT 1;
                                                        QUERY PLAN                                                        
--------------------------------------------------------------------------------------------------------------------------
 Limit  (cost=0.99..5.04 rows=1 width=454)
   ->  Nested Loop  (cost=0.99..5.04 rows=1 width=454)
         ->  Index Scan using file_rev_sha1_idx on file_rev  (cost=0.56..2.58 rows=1 width=405)
               Index Cond: ((sha1 IS NOT NULL) AND (sha1 = '3f242a192acc258bdfdb15194341943222222222222440c313'::bpchar))
         ->  Index Scan using file_ident_rev_idx on file_ident  (cost=0.43..2.45 rows=1 width=49)
               Index Cond: (rev_id = file_rev.id)
               Filter: (is_live AND (redirect_id IS NULL))

After all this debugging, asked on IRC and learned that I really shouldn't ever
use CHAR() (or even VARCHAR()). Will update the schema.

## Investigating Missing Rows

    fatcat_prod=# select count(*) from release_ident; => 53028167

Thought I had more than that previously? Table sizes were also bigger. Hrm.