私は若い開発者であり、データベース(PostgreSQL 9.3)の使用にあまり熟練していないので、本当に助けが必要なプロジェクトでいくつかの問題に遭遇しました。
私のプロジェクトは、デバイス(最大1000台以上のデバイス)からデータを収集することです。この場合、すべてのデバイスが毎秒1つのデータブロックを送信し、1時間あたり約300万行になります。
現在、すべてのデバイスの受信データを格納する1つの大きなテーブルがあります。
CREATE TABLE data_block(
id bigserial
timestamp timestamp
mac bigint
)
データブロックに含めることができる(またはできない)データにはいくつかの種類があるため、テーブルを参照する他のテーブルがありdata_block
ます。
CREATE TABLE dataA(
data_block_id bigserial
data
CONSTRAINT fkey FOREIGN KEY (data_block_id) REFERENCES data_block(id);
);
CREATE TABLE dataB(...);
CREATE TABLE dataC(...);
CREATE INDEX index_dataA_block_id ON dataA (data_block_id DESC);
...
1つのdata_blockに3x dataA、1x dataBがあるが、dataCがない可能性があります。
データは数週間保持されるため、このテーブルには約50億行を格納します。現時点では、テーブルに6億行まであり、クエリには非常に長い時間がかかります。私のselectステートメントは常にクエリを実行し、多くの場合はtime + macもクエリを実行するため、私はtimestamp
andとmac
でインデックスを作成することにしました。
CREATE INDEX index_ts_mac ON data_block (timestamp DESC, mac);
...しかし、クエリにはまだ時間がかかります。たとえば、1日と1つのMacのデータをクエリしました。
SELECT * FROM data_block
WHERE timestamp>'2014-09-15'
AND timestamp<'2014-09-17'
AND mac=123456789
Index Scan using index_ts_mac on data_block (cost=0.57..957307.24 rows=315409 width=32) (actual time=39.849..334534.972 rows=285857 loops=1)
Index Cond: ((timestamp > '2014-09-14 00:00:00'::timestamp without time zone) AND (timestamp < '2014-09-16 00:00:00'::timestamp without time zone) AND (mac = 123456789))
Total runtime: 334642.078 ms
クエリを実行する前に完全なバキュームを行いました。10秒未満のクエリを実行するために大きなテーブルでこのような問題を解決するエレガントな方法はありますか?
パーティション設定について読みましたが、dataA、dataB、dataCがdata_block_idを参照している場合は機能しませんか?それが何らかの方法で機能する場合、時間をかけて、またはMacでパーティションを作成する必要がありますか?
インデックスを別の方向に変更しました。最初のMAC、次にタイムスタンプ、そしてそれは多くのパフォーマンスを獲得します。
CREATE INDEX index_mac_ts ON data_block (mac, timestamp DESC);
それでも、クエリには30秒以上かかります。特にLEFT JOIN
、データテーブルを使用する場合は、ここでEXPLAIN ANALYZE
新しいインデックスとクエリのは:
EXPLAIN ANALYZE SELECT * FROM data_block WHERE mac = 123456789 AND timestamp < '2014-10-05 00:00:00' AND timestamp > '2014-10-04 00:00:00'
Bitmap Heap Scan on data_block (cost=1514.57..89137.07 rows=58667 width=28) (actual time=2420.842..32353.678 rows=51342 loops=1)
Recheck Cond: ((mac = 123456789) AND (timestamp < '2014-10-05 00:00:00'::timestamp without time zone) AND (timestamp > '2014-10-04 00:00:00'::timestamp without time zone))
-> Bitmap Index Scan on index_mac_ts (cost=0.00..1499.90 rows=58667 width=0) (actual time=2399.291..2399.291 rows=51342 loops=1)
Index Cond: ((mac = 123456789) AND (timestamp < '2014-10-05 00:00:00'::timestamp without time zone) AND (timestamp > '2014-10-04 00:00:00'::timestamp without time zone))
Total runtime: 32360.620 ms
残念ながら、私のハードウェアは厳しく制限されています。Intel i3-2100 @ 3.10Ghz、4GB RAMを使用しています。私の現在の設定は次のとおりです:
default_statistics_target = 100
maintenance_work_mem = 512MB
constraint_exclusion = on
checkpoint_completion_target = 0.9
effective_cache_size = 4GB
work_mem = 512MB
wal_buffers = 16MB
checkpoint_segments = 32
shared_buffers = 2GB
max_connections = 20
random_page_cost = 2