Гость
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / Вдруг затормозился вроде бы простой запрос. Наведите на мысль плз. / 18 сообщений из 18, страница 1 из 1
17.07.2018, 10:17
    #39674854
Alexey Trizno
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Вдруг затормозился вроде бы простой запрос. Наведите на мысль плз.
День добрый.

Есть pgsql 9.6, база на ssd, вроде бы все более менее по железу и настройкам.
Также есть примерно такой запрос (кусок другого, но тормозит сейчас именно эта часть):

Код: plsql
1.
2.
3.
4.
5.
6.
7.
select iv.id                                                                                                         
from                                                                                                                     
  interviews iv                                                                                                          
  inner join respondents r on (r.id = iv.respondent_id)                                                                  
  left outer join counter_interviews civ on (civ.counter_id = 27222 and civ.version_idx = 7 and civ.interview_id = iv.id)
where                                                                                                                    
  r.project_id = 737 and civ.id is null



План такой:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
Nested Loop  (cost=397193.59..439969.52 rows=1 width=8) (actual time=2642.358..74146.688 rows=165609 loops=1)
  ->  Hash Right Join  (cost=397193.16..439969.01 rows=1 width=16) (actual time=2641.861..5229.793 rows=9299931 loops=1)
        Hash Cond: (civ.interview_id = iv.id)
        Filter: (civ.id IS NULL)
        Rows Removed by Filter: 5179
        ->  Index Scan using ix_counterinterviews_counterid_versionidx on counter_interviews civ  (cost=0.56..53.82 rows=25 width=16) (actual time=0.055..2.806 rows=5179 loops=1)
              Index Cond: ((counter_id = 27222) AND (version_idx = 7))
        ->  Hash  (cost=245111.71..245111.71 rows=8748871 width=16) (actual time=2634.368..2634.368 rows=9305110 loops=1)
              Buckets: 131072  Batches: 256  Memory Usage: 2727kB
              ->  Seq Scan on interviews iv  (cost=0.00..245111.71 rows=8748871 width=16) (actual time=0.015..1322.721 rows=9305110 loops=1)
  ->  Index Scan using pk_respondents on respondents r  (cost=0.43..0.50 rows=1 width=8) (actual time=0.007..0.007 rows=0 loops=9299931)
        Index Cond: (id = iv.respondent_id)
        Filter: (project_id = 737)
        Rows Removed by Filter: 1
Planning time: 0.971 ms
Execution time: 74157.893 ms

Получаем порядка 74 сек, хотя обычно это все не более секунды.
Сейчас в interviews при project_id = 737 имеем 165609 записей, что много, но не смертельно.

Индекс есть в counter_interviews такой:

Код: plsql
1.
CREATE UNIQUE INDEX ix_counterinterviews_counterid_versionidx ON counter_interviews USING btree (counter_id, version_idx, interview_id)



Наведите пожалуйста на мысль. Вероятно пропустился какой-то индекс... да и не понятно, чего кэширование никак не спасает - один и тот же запрос постоянно выполняется за эти 74 секунды.
...
Рейтинг: 0 / 0
17.07.2018, 10:55
    #39674882
Ivan Durak
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Вдруг затормозился вроде бы простой запрос. Наведите на мысль плз.
9 ЛЯМОВ индекс сиков при Nested Loop по респондентам жрут все время - 70 секунд
тут напрашивается хэш джон на respondents
статистику обнови для начала.
а там может как раз индекс на pk_respondents тебе мешает.

ну и потом уже последовательность джоинов эффективнее другая. Видно что inner join respondents отбросит 90% лишнего из interviews. Потом на counter_interviews будет легче джойнить
...
Рейтинг: 0 / 0
17.07.2018, 12:30
    #39674954
Alexey Trizno
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Вдруг затормозился вроде бы простой запрос. Наведите на мысль плз.
Ivan Durak, спасибо, правда как-то очень наверное мудрый ответ - ничего не понял, что пробовать делать и куда смотреть.
Можно чуть более обычными словами?
...
Рейтинг: 0 / 0
17.07.2018, 12:41
    #39674966
Andy_OLAP
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Вдруг затормозился вроде бы простой запрос. Наведите на мысль плз.
Alexey TriznoIvan Durak, спасибо, правда как-то очень наверное мудрый ответ - ничего не понял, что пробовать делать и куда смотреть.
Можно чуть более обычными словами?
Можно. Краткая выдержка.
" Primary keys are constraints. Some constraints can create index(es) in order to work properly (but this fact should not be relied upon). F.ex. a UNIQUE constraint will create a unique index. Note, that only B-tree currently supports unique indexes. The PRIMARY KEY constraint is a combination of the UNIQUE and the NOT NULL constraints, so (currently) it only supports B-tree.

You can set up a hash index too , if you want (besides the PRIMARY KEY constraint) -- but you cannot make that unique.

CREATE INDEX name ON table USING hash (column);"
Читать таки тут .

То есть в целом нужно сделать примерно так CREATE INDEX respondents_id_hash ON respondents USING hash (ud);

И попробовать.
...
Рейтинг: 0 / 0
17.07.2018, 12:42
    #39674968
Andy_OLAP
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Вдруг затормозился вроде бы простой запрос. Наведите на мысль плз.
Andy_OLAP,

То есть CREATE INDEX respondents_id_hash ON respondents USING hash (id), небольшая опечатка, старость не радость.
...
Рейтинг: 0 / 0
17.07.2018, 13:14
    #39675007
Alexey Trizno
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Вдруг затормозился вроде бы простой запрос. Наведите на мысль плз.
Andy_OLAP, спасибо. Индекс сделал, но не изменилось совсем ничего по скорости. План теперь такой:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
Nested Loop  (cost=400212.50..443628.15 rows=1 width=8) (actual time=2834.281..77875.083 rows=178894 loops=1)
  ->  Hash Right Join  (cost=400212.50..443628.07 rows=1 width=16) (actual time=2834.241..5616.894 rows=9326660 loops=1)
        Hash Cond: (civ.interview_id = iv.id)
        Filter: (civ.id IS NULL)
        Rows Removed by Filter: 5275
        ->  Index Scan using ix_counterinterviews_counterid_versionidx on counter_interviews civ  (cost=0.56..154.28 rows=78 width=16) (actual time=0.061..2.430 rows=5275 loops=1)
              Index Cond: ((counter_id = 27222) AND (version_idx = 7))
        ->  Hash  (cost=246214.53..246214.53 rows=8859153 width=16) (actual time=2828.012..2828.012 rows=9331935 loops=1)
              Buckets: 131072  Batches: 256  Memory Usage: 2731kB
              ->  Seq Scan on interviews iv  (cost=0.00..246214.53 rows=8859153 width=16) (actual time=0.006..1419.091 rows=9331935 loops=1)
  ->  Index Scan using ix_respondents_id_hash on respondents r  (cost=0.00..0.07 rows=1 width=8) (actual time=0.007..0.007 rows=0 loops=9326660)
        Index Cond: (id = iv.respondent_id)
        Rows Removed by Index Recheck: 0
        Filter: (project_id = 737)
        Rows Removed by Filter: 1
Planning time: 1.128 ms
Execution time: 77887.715 ms
...
Рейтинг: 0 / 0
17.07.2018, 13:17
    #39675009
Alexey Trizno
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Вдруг затормозился вроде бы простой запрос. Наведите на мысль плз.
Andy_OLAP,

Возможно кроме индексов есть смысл таки изменить сам запрос? Хотя простой же он совсем...
...
Рейтинг: 0 / 0
17.07.2018, 13:18
    #39675011
Andy_OLAP
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Вдруг затормозился вроде бы простой запрос. Наведите на мысль плз.
Alexey TriznoAndy_OLAP, спасибо. Индекс сделал, но не изменилось совсем ничего по скорости. План теперь такой:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
Nested Loop  (cost=400212.50..443628.15 rows=1 width=8) (actual time=2834.281..77875.083 rows=178894 loops=1)
  ->  Hash Right Join  (cost=400212.50..443628.07 rows=1 width=16) (actual time=2834.241..5616.894 rows=9326660 loops=1)
        Hash Cond: (civ.interview_id = iv.id)
        Filter: (civ.id IS NULL)
        Rows Removed by Filter: 5275
        ->  Index Scan using ix_counterinterviews_counterid_versionidx on counter_interviews civ  (cost=0.56..154.28 rows=78 width=16) (actual time=0.061..2.430 rows=5275 loops=1)
              Index Cond: ((counter_id = 27222) AND (version_idx = 7))
        ->  Hash  (cost=246214.53..246214.53 rows=8859153 width=16) (actual time=2828.012..2828.012 rows=9331935 loops=1)
              Buckets: 131072  Batches: 256  Memory Usage: 2731kB
              ->  Seq Scan on interviews iv  (cost=0.00..246214.53 rows=8859153 width=16) (actual time=0.006..1419.091 rows=9331935 loops=1)
  ->  Index Scan using ix_respondents_id_hash on respondents r  (cost=0.00..0.07 rows=1 width=8) (actual time=0.007..0.007 rows=0 loops=9326660)
        Index Cond: (id = iv.respondent_id)
        Rows Removed by Index Recheck: 0
        Filter: (project_id = 737)
        Rows Removed by Filter: 1
Planning time: 1.128 ms
Execution time: 77887.715 ms

Таки нужно сделать ANALYZE respondents после создания нового индекса.
И можно использовать set enable_nestloop = False.
...
Рейтинг: 0 / 0
17.07.2018, 13:24
    #39675016
Andy_OLAP
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Вдруг затормозился вроде бы простой запрос. Наведите на мысль плз.
Alexey TriznoAndy_OLAP,

Возможно кроме индексов есть смысл таки изменить сам запрос? Хотя простой же он совсем...
Можно попробовать.
Было
Код: plsql
1.
2.
3.
4.
5.
6.
7.
select iv.id                                                                                                         
from                                                                                                                     
  interviews iv                                                                                                          
  inner join respondents r on (r.id = iv.respondent_id)                                                                  
  left outer join counter_interviews civ on (civ.counter_id = 27222 and civ.version_idx = 7 and civ.interview_id = iv.id)
where                                                                                                                    
  r.project_id = 737 and civ.id is null


Стало
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
WITH t AS (
  SELECT id
  FROM respondents
  WHERE project_id = 737
)
select iv.id                                                                                                         
from                                                                                                                     
  interviews iv                                                                                                          
  inner join t r on (t.id = iv.respondent_id)                                                                  
  left outer join counter_interviews civ on (civ.counter_id = 27222 and civ.version_idx = 7 and civ.interview_id = iv.id)
where                                                                                                                    
civ.id is null



А можно еще сделать простой из 2 столбцов CREATE INDEX respondents_id_project_id ON respondents USING (project_id,id);
Вместо hash index.
...
Рейтинг: 0 / 0
17.07.2018, 13:26
    #39675017
Andy_OLAP
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Вдруг затормозился вроде бы простой запрос. Наведите на мысль плз.
Alexey Trizno,

Вы поймите, смысл форума не в том, чтобы выдать Вам сразу готовый продукт, а в том, чтобы дать несколько полуфабрикатов и инструкцию по доводке напильником. Чтобы Вы попробовали на вкус разное и решили уже с пониманием, что именно нужно здесь, а что там, и почему так.
...
Рейтинг: 0 / 0
17.07.2018, 14:06
    #39675039
Alexey Trizno
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Вдруг затормозился вроде бы простой запрос. Наведите на мысль плз.
Andy_OLAPА можно еще сделать простой из 2 столбцов CREATE INDEX respondents_id_project_id ON respondents USING (project_id,id);
Вместо hash index.

Сделал:
Код: plaintext
1.
2.
CREATE INDEX ix_respondents_projectid_id ON respondents USING btree (project_id, id);
ANALYZE respondents;

Что-то таки поменялось (сам запрос пока старый):

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
Nested Loop  (cost=400212.93..443630.49 rows=1 width=8) (actual time=3159.431..19037.653 rows=181371 loops=1)
  ->  Hash Right Join  (cost=400212.50..443629.99 rows=1 width=16) (actual time=3159.407..5510.064 rows=9333576 loops=1)
        Hash Cond: (civ.interview_id = iv.id)
        Filter: (civ.id IS NULL)
        Rows Removed by Filter: 5275
        ->  Index Scan using ix_counterinterviews_counterid_versionidx on counter_interviews civ  (cost=0.56..156.17 rows=79 width=16) (actual time=0.027..2.028 rows=5275 loops=1)
              Index Cond: ((counter_id = 27222) AND (version_idx = 7))
        ->  Hash  (cost=246214.53..246214.53 rows=8859153 width=16) (actual time=3154.284..3154.284 rows=9338851 loops=1)
              Buckets: 131072  Batches: 256  Memory Usage: 2733kB
              ->  Seq Scan on interviews iv  (cost=0.00..246214.53 rows=8859153 width=16) (actual time=0.011..1563.148 rows=9338851 loops=1)
  ->  Index Only Scan using ix_respondents_projectid_id on respondents r  (cost=0.43..0.49 rows=1 width=8) (actual time=0.001..0.001 rows=0 loops=9333576)
        Index Cond: ((project_id = 737) AND (id = iv.respondent_id))
        Heap Fetches: 181207
Planning time: 0.306 ms
Execution time: 19045.591 ms
...
Рейтинг: 0 / 0
17.07.2018, 14:11
    #39675049
Andy_OLAP
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Вдруг затормозился вроде бы простой запрос. Наведите на мысль плз.
Alexey TriznoAndy_OLAPА можно еще сделать простой из 2 столбцов CREATE INDEX respondents_id_project_id ON respondents USING (project_id,id);
Вместо hash index.

Сделал:
Код: plaintext
1.
2.
CREATE INDEX ix_respondents_projectid_id ON respondents USING btree (project_id, id);
ANALYZE respondents;

Что-то таки поменялось
Ну и теперь можно сделать и посмотреть, что поменялось.
Код: plsql
1.
2.
CREATE INDEX ix_respondents_projectid_id ON respondents USING hash (project_id);
ANALYZE respondents;


А затем иначе и сравнить.
Ну и теперь можно сделать и посмотреть, что поменялось.
Код: plsql
1.
2.
CREATE INDEX ix_respondents_projectid_id ON respondents USING btree (project_id);
ANALYZE respondents;
...
Рейтинг: 0 / 0
17.07.2018, 14:11
    #39675051
Alexey Trizno
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Вдруг затормозился вроде бы простой запрос. Наведите на мысль плз.
Andy_OLAPВы поймите, смысл форума не в том, чтобы выдать Вам сразу готовый продукт, а в том, чтобы дать несколько полуфабрикатов и инструкцию по доводке напильником. Чтобы Вы попробовали на вкус разное и решили уже с пониманием, что именно нужно здесь, а что там, и почему так.

Это я конечно понимаю. Мысль про индекс по project_id + id - спасибо, получили index only scan, это явно немного помогло.

Мне просто после многих лет жизни с mssql, который сам мудрит и оптимизирует кривые запросы, сейчас несколько сложно :) Пытаюсь пробиться. Разбивка запроса на отдельные with... - это как раз то, к чему нет привычки, т.к. по ощущениям - это задача оптимизатора как раз, ему более понятно что и как лучше сделать, согласно накопленной статистики, имеющихся данных в кэшах и т.д.
...
Рейтинг: 0 / 0
17.07.2018, 14:16
    #39675056
Andy_OLAP
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Вдруг затормозился вроде бы простой запрос. Наведите на мысль плз.
Alexey TriznoМне просто после многих лет жизни с mssql, который сам мудрит и оптимизирует кривые запросы, сейчас несколько сложно...cогласно накопленной статистики, имеющихся данных в кэшах и т.д.
Тут такое дело - MSSQL это все-таки блокировочник, а PosgreSQL - самая кривая реализация из всех MVCC, даже MySQL впереди, куда уж до Oracle. А в туплах накопленная статистика - это что-то такое, что никак не накопленная статистика по строкам. Понимаете? Поэтому Вам кажется планировщик кривым, а разработчики изнутри уже давно привыкли, что нужно с бубном танцевать. И у них не вызывает сочувствия и понимания тот факт, что в MSSQL все проще.

Не хотят заказчики платить за MSSQL Enterprice + CAL - лучше делать на MSSQL Express несколько небольших баз-прослоек, а оттуда все сливать в большую базу PostrgeSQL, если совсем никак.
...
Рейтинг: 0 / 0
17.07.2018, 14:25
    #39675061
Alexey Trizno
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Вдруг затормозился вроде бы простой запрос. Наведите на мысль плз.
Andy_OLAP,

Про нежелание платить - да, потому и ушли. Но в защиту PG тоже могу сказать, что за годы жизни на MS (причем в режиме версионности, без блокировок) - тоже наступали на кучу внезапных проблем с производительностью, которые как появлялись, так и потом пропадали. А в PG оно как бы честнее... но требует больше мозга.

Насчет with... попробовал вынести отдельно respontents и такой запрос вообще залип, не дождался завершения:

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
with _r as (
  select id from respondents where project_id = 737
)
select iv.id                                                                                                         
from                                                                                                                     
  interviews iv                                                                                                          
  inner join _r r on (r.id = iv.respondent_id)                                                                  
  left outer join counter_interviews civ on (civ.counter_id = 27222 and civ.version_idx = 7 and civ.interview_id = iv.id)
where                                                                                                                    
  civ.id is null
...
Рейтинг: 0 / 0
17.07.2018, 14:32
    #39675072
Andy_OLAP
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Вдруг затормозился вроде бы простой запрос. Наведите на мысль плз.
Alexey TriznoНасчет with... попробовал вынести отдельно respontents и такой запрос вообще залип, не дождался завершения:

А Вы посмотрите EXPLAIN, без EXPLAIN ANALYZE. И подумайте, почему Вы решили, что "А в PG оно как бы честнее ... но требует больше мозга" :)

Кроме того, тесты проводить следует на отдельной таблице respondents_copy с primary key, куда заливаете строки из respondents, затем создаете один индекс новый. Потом удаляете таблицу-копию и по новой.

А Вы наверняка на одной и той же таблице все тестируете.
...
Рейтинг: 0 / 0
17.07.2018, 14:34
    #39675074
Andy_OLAP
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Вдруг затормозился вроде бы простой запрос. Наведите на мысль плз.
Alexey Trizno за годы жизни на MS (причем в режиме версионности, без блокировок) - тоже наступали на кучу внезапных проблем с производительностью , которые как появлялись, так и потом пропадали
И называлась эта одна проблема очень просто - "merge join вместо nl или inner join при отсутствии update statistics with fullscan".
...
Рейтинг: 0 / 0
17.07.2018, 15:25
    #39675110
Alexey Trizno
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Вдруг затормозился вроде бы простой запрос. Наведите на мысль плз.
Andy_OLAP,

Спасибо. Пока остановились на индексе по project_id + id, его наличие позволяет в этих запросах укладываться по скорости в приемлемые рамки.
...
Рейтинг: 0 / 0
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / Вдруг затормозился вроде бы простой запрос. Наведите на мысль плз. / 18 сообщений из 18, страница 1 из 1
Целевая тема:
Создать новую тему:
Автор:
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]