記事一覧はこちら

PostgreSQLに770万件のデータを突っ込んでindexのサイズを調べてみた

psql (PostgreSQL) 9.4.1 vpsのmongodbにTwitterのログデータ770万件突っ込んでるんだけどselelctが遅すぎて全く使い物にならない。 投稿者のid、投稿日時にインデックス貼ってるんだけどそれすら使い物にならない。

MongoDBを真面目に使ってみた - ひよくあブログ collStats — MongoDB Manual 3.0 dbStats — MongoDB Manual 3.0

db.tweets.stats(1024*1024)
{
    "ns" : "twitter.tweets",
    "count" : 7771002, //ドキュメント数
    "size" : 25005,//容量。25GB
    "avgObjSize" : 3374,
    "storageSize" : 26104,
    "numExtents" : 33,
    "nindexes" : 9,
    "lastExtentSize" : 2046,
    "paddingFactor" : 1,
    "systemFlags" : 0,
    "userFlags" : 0,
    "totalIndexSize" : 2813,//全てのインデックスの合計サイズ 2.8GB
    "indexSizes" : {
        "_id_" : 239,
        "data_unique_key" : 438,//NumberLong(645577000000000000)
        "data_created_at" : 237,//NumberLong(1442752683000)
        "message_type" : 246,//"tweet"
        "data_user_id" : 334,//NumberLong(645577000000000000)
        "data_entities_user_mentions_id" : 283,//NumberLong(645577000000000000)
        "data_retweet_count" : 313,//NumberInt(100)
        "data_favorite_count" : 344,//NumberInt(100)
        "tweet_id" : 376 //NumberLong(645577000000000000)
    },
    "ok" : 1
}

300MBの場合、1レコードあたり40byte

んでbigintとtimestampとenumの項目を作って7770000件のレコードを入れて試してみた。Disk Usage - PostgreSQL wikiを参考に。

SELECT d.datname AS Name,  pg_catalog.pg_get_userbyid(d.datdba) AS Owner,
    CASE WHEN pg_catalog.has_database_privilege(d.datname, 'CONNECT')
        THEN pg_catalog.pg_size_pretty(pg_catalog.pg_database_size(d.datname))
        ELSE 'No Access'
    END AS SIZE
FROM pg_catalog.pg_database d
    ORDER BY
    CASE WHEN pg_catalog.has_database_privilege(d.datname, 'CONNECT')
        THEN pg_catalog.pg_database_size(d.datname)
        ELSE NULL
    END DESC -- nulls first

name      owner    size
--------------------------
postgres  postgres 1270 MB
SELECT nspname || '.' || relname AS "relation",
    pg_size_pretty(pg_relation_size(C.oid)) AS "size"
  FROM pg_class C
  LEFT JOIN pg_namespace N ON (N.oid = C.relnamespace)
  WHERE nspname NOT IN ('pg_catalog', 'information_schema')
  ORDER BY pg_relation_size(C.oid) DESC
 
relation                       size
-------------------------------------
index_disk_size_test.test      387 MB //データベース
index_disk_size_test.enu_non   211 MB //インデックス 非ユニーク
index_disk_size_test.index_non 167 MB //インデックス 非ユニーク
index_disk_size_test.ts_non    167 MB //インデックス 非ユニーク
index_disk_size_test.ts_unq    166 MB //インデックス ユニーク
index_disk_size_test.index_unq 166 MB //インデックス ユニーク
SELECT nspname || '.' || relname AS "relation",
    pg_size_pretty(pg_total_relation_size(C.oid)) AS "total_size"
  FROM pg_class C
  LEFT JOIN pg_namespace N ON (N.oid = C.relnamespace)
  WHERE nspname NOT IN ('pg_catalog', 'information_schema')
    AND C.relkind <> 'i'
    AND nspname !~ '^pg_toast'
  ORDER BY pg_total_relation_size(C.oid) DESC
relation                  total_size
------------------------------------
index_disk_size_test.test 1264 MB //↑の387+211~の合計と同じ

enumは211MB/7770000≒28byte timestampとbigintは166MB≒22byte

容量は減ってるけどあんま劇的ではない・・・1/10とかになってくれればいいのに。777万件のレコードは個人が扱うには多すぎるんだろうか・・・ いやいや現時点のmongoDBシステムの問題点は検索がくっそ遅いことが原因であってそっちも調べないと。本データをコピーしよっかなあ