Изменить план запросов Postgres 9.0 - PullRequest
0 голосов
/ 24 февраля 2012

Мне нужна дополнительная информация о том, как изменить план запросов Postgres 9..0.

У меня есть запрос:

SELECT
    max(creation_date) 
FROM 
    statistics_loged_users 
WHERE
    school_id    = 338 and 
    group_id     = 3 and 
    usr_id       = 243431;

И объяснить анализ вывода:

"Aggregate  (cost=1518.56..1518.57 rows=1 width=8) (actual time=410.459..410.459 rows=1 loops=1)"
"  ->  Bitmap Heap Scan on statistics_loged_users  (cost=993.96..1518.55 rows=1 width=8) (actual time=410.025..410.406 rows=210 loops=1)"
"        Recheck Cond: ((group_id = 3) AND (usr_id = 243431))"
"        Filter: (school_id = 338)"
"        ->  BitmapAnd  (cost=993.96..993.96 rows=133 width=0) (actual time=409.521..409.521 rows=0 loops=1)"
"              ->  Bitmap Index Scan on statistics_loged_users_idx2  (cost=0.00..496.85 rows=26669 width=0) (actual time=375.770..375.770 rows=3050697 loops=1)"
"                    Index Cond: (group_id = 3)"
"              ->  Bitmap Index Scan on statistics_loged_users_idx  (cost=0.00..496.85 rows=26669 width=0) (actual time=0.077..0.077 rows=210 loops=1)"
"                    Index Cond: (usr_id = 243431)"
"Total runtime: 411.419 ms"

Мы видим, что первый фильтр по group_id. Этот стол очень очень большой :) Таким образом, во множестве строк одинаковое значение group_id, но гораздо меньше строк с одинаковым значением usr_id.

Вопрос в том, как мне сообщить плану запросов, что первый фильтр должен быть usr_id.

Я создаю индекс для group_id и usr_id, и я получаю производительность, но там мне нужно знать, как изменить план запроса, это на будущее:)

Ответы [ 2 ]

1 голос
/ 28 февраля 2012

Планировщик PostgreSQL не принимает подсказки так, как вам нужно. Самый простой способ достичь желаемого - переписать запрос.

Анализируя вывод EXPLAIN ANALYZE, становится ясно, что большую часть времени проводит в следующем разделе:

"-> Сканирование индекса растрового изображения для statistics_loged_users_idx2 (стоимость = 0.00..496.85 строк = 26669 ширина = 0) (фактическое время = 375.770..375.770 строк = 3050697 циклов = 1)"

"Index Cond: (group_id = 3)"

Если вы перепишете свой запрос, чтобы сначала искать только usr_id и school_id, вы получите то, что хотите.

SELECT
    max(creation_date) 
FROM 
(
    SELECT 
        group_id, creation_date
    FROM
        statistics_loged_users 
    WHERE
        school_id    = 338 and 
        usr_id       = 243431
) AS cd
WHERE 
group_id = 3;
1 голос
/ 24 февраля 2012

В текущем запросе теперь нужно использовать два индекса: statistics_loged_users_idx и statistics_loged_users_idx2, один индекс может быть быстрее. Создайте отдельный индекс для usr_id, group_id и school_id и попробуйте другой порядок столбцов в индексе.

Два примера:

CREATE INDEX idx_triple_index ON statistics_loged_users(usr_id, group_id, school_id);

CREATE INDEX idx_triple_2_index ON statistics_loged_users(usr_id, school_id, group_id);

Попробуйте и проверьте снова EXPLAIN ANALYZE.

...