PostgreSQL Slow DISTINCT WHERE - PullRequest
       10

PostgreSQL Slow DISTINCT WHERE

0 голосов
/ 20 февраля 2019

Представьте себе следующую таблицу:

CREATE TABLE drops(
    id BIGSERIAL PRIMARY KEY,
    loc VARCHAR(5) NOT NULL,
    tag INT NOT NULL
);

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

SELECT DISTINCT loc
FROM drops
WHERE tag = '1'
GROUP BY loc;

IЯ не уверен, что это из-за размера (его 9-метровые строки большие!) или из-за того, что я неэффективен, но запрос занимает слишком много времени, чтобы пользователи могли эффективно его использовать.В то время, когда я писал это, вышеприведенный запрос занял у меня 1:14 минуты.

Есть ли какие-либо приемы или методы, которые я могу использовать, чтобы сократить это до нескольких секунд?

Очень признателен!

План выполнения:

"Unique  (cost=1967352.72..1967407.22 rows=41 width=4) (actual time=40890.768..40894.984 rows=30 loops=1)"
"  ->  Group  (cost=1967352.72..1967407.12 rows=41 width=4) (actual time=40890.767..40894.972 rows=30 loops=1)"
"        Group Key: loc"
"        ->  Gather Merge  (cost=1967352.72..1967406.92 rows=82 width=4) (actual time=40890.765..40895.031 rows=88 loops=1)"
"              Workers Planned: 2"
"              Workers Launched: 2"
"              ->  Group  (cost=1966352.70..1966397.43 rows=41 width=4) (actual time=40879.910..40883.362 rows=29 loops=3)"
"                    Group Key: loc"
"                    ->  Sort  (cost=1966352.70..1966375.06 rows=8946 width=4) (actual time=40879.907..40881.154 rows=19129 loops=3)"
"                          Sort Key: loc"
"                          Sort Method: quicksort  Memory: 1660kB"
"                          ->  Parallel Seq Scan on drops  (cost=0.00..1965765.53 rows=8946 width=4) (actual time=1.341..40858.553 rows=19129 loops=3)"
"                                Filter: (tag = 1)"
"                                Rows Removed by Filter: 3113338"
"Planning time: 0.146 ms"
"Execution time: 40895.280 ms"

Таблица проиндексирована на loc и tag.

Ответы [ 2 ]

0 голосов
/ 20 февраля 2019

Если вы использовали предложение GROUP BY, тогда нет необходимости использовать ключевое слово DISTINCT.Отказ от этого должен ускорить время выполнения запроса.

0 голосов
/ 20 февраля 2019

Ваши 40 секунд тратятся на последовательное чтение всей таблицы, выбрасывая 3113338 строк, оставляя только 19129.

Средство простое:

CREATE INDEX ON drops(tag);

Но вы говорите, что уже сделалиэто, но мне трудно поверить.Какую команду вы использовали?

Измените условие в запросе с

WHERE tag = '1'

на

WHERE tag = 1

Это работает, потому что '1' является литералом, но не пытайтесь сравнивать строки и числа.

И, как уже упоминалось, сохраняйте либо DISTINCT, либо GROUP BY, но не оба.

...