私は SQL にかなり慣れていないので、おそらくインデックスの使用を改善することによって、postgres で複雑な SQL クエリを高速化する方法を考え出そうとしています。これはクエリです:
SELECT
(SELECT ev.code FROM classification_item ci, enumeration_value ev
WHERE ev.key_id = :ak_0
AND ci.entry_id = t.id AND ci.value_id = ev.id) AS axis_0,
(SELECT ev.code FROM classification_item ci, enumeration_value ev
WHERE ev.key_id = :ak_1
AND ci.entry_id = t.id AND ci.value_id = ev.id) AS axis_1,
SUM(t.amount) as amount,
(SELECT ev.code FROM classification_item ci, enumeration_value ev
WHERE ev.key_id = :key_time_id
AND ci.entry_id = t.id AND ci.value_id = ev.id) AS time
FROM "entry" t
WHERE t.dataset_id = :dataset_id
AND t.id IN (SELECT ci.entry_id FROM classification_item ci, enumeration_value ev
WHERE ev.key_id = :k_0
AND ev.code = :v_0 AND ci.value_id = ev.id)
GROUP BY time, axis_0, axis_1
これは基本的にデータベーススキーマです (Pylons で定義されています):
table_dataset = Table('dataset', meta.metadata,
Column('id', Integer, primary_key=True),
)
table_entry = Table('entry', meta.metadata,
Column('id', Integer, primary_key=True),
Column('dataset_id', Integer, ForeignKey('dataset.id')),
Column('amount', Float()),
)
table_classification_item = Table('classification_item', meta.metadata,
Column('id', Integer, primary_key=True),
Column('entry_id', Integer, ForeignKey('entry.id'), index=True),
Column('value_id', Integer, ForeignKey('enumeration_value.id'), index=True)
)
table_enumeration_value = Table('enumeration_value', meta.metadata,
Column('id', Integer, primary_key=True),
Column('key_id', Integer, ForeignKey('key.id'), index=True),
Column('code', UnicodeText(), index=True),
)
また、次のようなインデックスがあります。
"dataset_pkey" PRIMARY KEY, btree (id)
"entry_pkey" PRIMARY KEY, btree (id)
"classification_item_pkey" PRIMARY KEY, btree (id)
"ix_classification_item_entry_id" btree (entry_id)
"ix_classification_item_value_id" btree (value_id)
"enumeration_value_pkey" PRIMARY KEY, btree (id)
"ix_enumeration_value_code" btree (code)
"ix_enumeration_value_key_id" btree (key_id)
クエリを高速化する明らかなインデックスがありませんか? 特に:
- 「クラスター化」インデックスを使用する必要がありますか?
- にもインデックス
amount
を作成する必要がありますentry
か、それとも違いはありませSUM(t.amount) as amount
んか?
ご協力いただきありがとうございます。これはかなり複雑な質問であることは承知していますので、改善するために何かできることがあれば教えてください。
- - - アップデート - - - - - - -
上記のクエリのEXPLAIN ANALYZE からの出力。