Как я могу ускорить этот запрос SQL? - PullRequest
0 голосов
/ 03 ноября 2010

Я довольно новичок в SQL и пытаюсь понять, как ускорить сложный SQL-запрос в postgres, возможно, за счет улучшения моего использования индексов. Это запрос:

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 по вышеуказанному запросу.

Ответы [ 2 ]

1 голос
/ 03 ноября 2010

Если таблица enumeration_value мала, я думаю, вы можете добиться некоторого улучшения, сделав axis_1 и axis_0 в качестве объединения и добавив дополнительный индекс.

как то так (не проверено)

CREATE INDEX idx_ci_vi_ei ON classification_item(value_id, entry_id);

CREATE INDEX idx_id_ki ON enumeration_value(id, key_id);

SELECT
    ci_0.code AS axis_0,
    ci_1.code AS axis_1,
    SUM(t.amount) as amount,
    ci_t.code AS time
FROM 
   "entry" t,
   (SELECT ev.code FROM classification_item ci, enumeration_value ev
        WHERE ev.key_id = :ak_0 AND ci.value_id = ev.id) ci_0,
   (SELECT ev.code FROM classification_item ci, enumeration_value ev
        WHERE ev.key_id = :ak_1 AND ci.value_id = ev.id) ci_1,
   (SELECT ev.code FROM classification_item ci, enumeration_value ev
        WHERE ev.key_id = :key_time_id AND ci.value_id = ev.id) ci_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)
AND t.id = ci_0.entry_id AND t.id = ci_1.entry_id AND t.id = ci_t.entry_id
GROUP BY time, axis_0, axis_1
0 голосов
/ 03 ноября 2010

Что может EXPLAIN ANALYZE сказать о плане запросов?

...