Что я должен индексировать на эту базу данных? - PullRequest
2 голосов
/ 15 марта 2012

У меня есть запрос, который делает несколько соединений.

SELECT feedback.note as notes, 
to_char(feedback.data_compilazione,'DD/MM/YYYY') as date, 
CAST(feedback.punteggio AS INT) as score, 
upper(substring(cliente.nome from '^.') || '.' || 
substring(cliente.cognome from '^.') || '.') as customer, 
testo.testo as nation FROM feedback 
JOIN prenotazione ON prenotazione.id = feedback.id_prenotazione 
JOIN cliente ON cliente.id = prenotazione.id_cliente 
JOIN struttura ON struttura.id = prenotazione.id_struttura 
JOIN lingua ON cliente.id_lingua = lingua.id 
JOIN nazione ON cliente.codice_nazione = nazione.codice_iso 
JOIN testo ON testo.nome_tabella = 'nazione' AND testo.id_record = nazione.id AND
testo.id_lingua = lingua.id AND testo.id_tipo_testo = 1 WHERE struttura.id = 43 AND
lingua.sigla = E'en' AND feedback.punteggio >= 3 AND feedback.note <> '' 
ORDER BY feedback.data_compilazione DESC LIMIT 5

Моя проблема в том, что у меня нет явного индекса для моих таблиц.

Это означает, что выполнение этого запроса заняло много-много времени.

AFAIK postresql создает «неявный» индекс каждый раз при объявлении первичного ключа, поэтому мне не нужно добавлять его «явно».

Это EXPLAIN запроса

"Limit  (cost=212.72..212.73 rows=1 width=208)"
"  ->  Sort  (cost=212.72..212.73 rows=1 width=208)"
"        Sort Key: feedback.data_compilazione"
"        ->  Nested Loop  (cost=1.11..212.71 rows=1 width=208)"
"              ->  Nested Loop  (cost=1.11..206.86 rows=1 width=212)"
"                    Join Filter: (("outer".codice_nazione)::text = ("inner".codice_iso)::text)"
"                    ->  Nested Loop  (cost=1.11..201.63 rows=1 width=223)"
"                          ->  Nested Loop  (cost=1.11..195.60 rows=1 width=187)"
"                                Join Filter: ("outer".id = "inner".id_cliente)"
"                                ->  Nested Loop  (cost=1.11..45.18 rows=1 width=183)"
"                                      Join Filter: ("outer".id_lingua =    "inner".id_lingua)"
"                                      ->  Index Scan using testo_pkey on testo  (cost=0.00..6.27 rows=1 width=40)"
"                                            Index Cond: (((nome_tabella)::text = 'nazione'::text) AND (id_tipo_testo = 1))"
"                                      ->  Hash Join  (cost=1.11..38.86 rows=4 width=155)"
"                                            Hash Cond: ("outer".id_lingua = "inner".id)"
"                                            ->  Seq Scan on cliente  (cost=0.00..33.47 rows=847 width=151)"
"                                            ->  Hash  (cost=1.11..1.11 rows=1 width=4)"
"                                                  ->  Seq Scan on lingua  (cost=0.00..1.11 rows=1 width=4)"
"                                                        Filter: ((sigla)::text = 'en'::text)"
"                                ->  Seq Scan on prenotazione  (cost=0.00..150.05 rows=30 width=12)"
"                                      Filter: (43 = id_struttura)"
"                          ->  Index Scan using feedback_id_prenotazione_key on feedback  (cost=0.00..6.01 rows=1 width=44)"
"                                Index Cond: ("outer".id = feedback.id_prenotazione)"
"                                Filter: ((punteggio >= 3::double precision) AND (note <> ''::text))"
"                    ->  Index Scan using nazione_pkey on nazione  (cost=0.00..5.21 rows=1 width=11)"
"                          Index Cond: ("outer".id_record = nazione.id)"
"              ->  Index Scan using struttura_pkey on struttura  (cost=0.00..5.82 rows=1 width=4)"
"                    Index Cond: (id = 43)"

Так что я перестал думать об индексации в БД. Какова лучшая практика для создания индекса? Решение: создать индекс для каждого объединенного поля?

А в мою БД, что вы предлагаете проиндексировать?

Я сделал несколько попыток (по существу индексировал каждое объединенное поле), и теперь запрос выполняется быстрее, но не быстро (около шести секунд, чтобы получить нулевые строки). Я полагаю, что мое решение не самое лучшее.

Кто-нибудь может направить мой взгляд в правильном направлении?

РЕДАКТИРОВАТЬ

Если я добавлю только индекс (на prenotazione.id_cliente), все будет работать за несколько секунд (1,5 об). Итак, зачем добавлять все индексы для ключей FOREIGN, чтобы мой запрос работал медленнее?

1 Ответ

3 голосов
/ 15 марта 2012

В качестве первого практического правила, даже не глядя на план запроса, я бы определенно поместил индексы для внешних ключей, которые имеют высокую (> 100 различных значений) селективность.

Некоторые базы данных помещают их без запроса, Postgres - нет. Мы говорим об индексах на ИНОСТРАННЫХ ключах, а не НАЧАЛЬНЫХ (они, очевидно, всегда предоставляются).

Например, prenotazione.id_struttura и feedback.id_prenotazione являются вероятными кандидатами.

С другой стороны, столбец weekday, состоящий из 7 различных значений, не получит выгоды от индекса, если только нет тысяч понедельников и очень мало воскресений, и в этом случае индекс является выборочным для некоторых значений.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...