|
как ускорить запрос | ☑ | ||
---|---|---|---|---|
0
GANR
31.08.23
✎
12:56
|
Всем добрый день. Как построить индекс, чтобы запрос работал быстрее??
-- установил расширения CREATE EXTENSION IF NOT EXISTS pg_trgm; CREATE EXTENSION IF NOT EXISTS btree_gin; -- построил составной gin индекс DROP INDEX IF EXISTS idx_gin_svjul_ltrim_inn_id; CREATE INDEX IF NOT EXISTS idx_gin_svjul_ltrim_inn_id ON svjul USING gin (ltrim(data ->> 'INN') gin_trgm_ops, id); -- запрос к таблице (размер более 100 Гб) SELECT * FROM svjul svjul1 WHERE ltrim(svjul1.data ->> 'INN') ilike '7839074221%' ORDER BY svjul1.id ASC LIMIT 20 OFFSET 0; -- ожидаемый результат: select выше работает быстро -- фактический результат: select выше работает мелденно и в плане запроса не видно срабатывания индекса |
|||
1
Волшебник
31.08.23
✎
13:00
|
уберите звёздочку
уберите ltrim Вытащите INN в отдельное поле таблицы |
|||
2
GANR
31.08.23
✎
13:01
|
(1) Ни запрос, ни структуру таблицы менять нельзя. В этом то и прикол.
|
|||
3
asady
31.08.23
✎
13:18
|
В SELECT * FROM svjul svjul1
svjul и svjul1 = это две таблицы или svjul1 - алиас таблицы svjul ? |
|||
4
stopa85
31.08.23
✎
13:20
|
(0) хоть бы сказал, что за СУБД.
|
|||
5
Волшебник
31.08.23
✎
13:22
|
(3) очевидно да
(4) PostgreSQL, судя по префиксу "pg" и попытке индексировать json-поле |
|||
6
stopa85
31.08.23
✎
13:25
|
(5) тогда где комментарий про VACUUM FULL?
(0) Нужен explain без этого никак |
|||
7
GANR
31.08.23
✎
13:35
|
(3) (4) подтверждаю слова (5)
|
|||
8
GANR
31.08.23
✎
13:38
|
(6) появилось предположение, что постгрес при сортировке по id решает использовать первичный ключ вместо индекса (коим id является)
Index Scan using svjul_pkey on svjul as svjul Filter: (ltrim((data ->> 'INN'::text)) ~~* '7839074221%'::text) сейчас попробую изменить order by, может быть подмена первичного ключа спасет отца русской демократи |
|||
9
GANR
31.08.23
✎
13:40
|
(6) (5) я в (8) был прав, стоило мне заменить в секции ORDER BY id на другое поле и запрос заработал быстро!!
SELECT * FROM svjul WHERE ltrim(data ->> 'INN') ilike '7839074221%' ORDER BY created ASC LIMIT 20 OFFSET 0; |
|||
10
stopa85
31.08.23
✎
13:51
|
А какое количество строк он возвращает и ожидает вернуть, где оценки?
|
|||
11
GANR
31.08.23
✎
13:56
|
(10) По одному ИНН 1-3 записи, LIMIT 20 стоит ограничитель, вот только без составного индекса этот ограничитель будет работать медленно. Видимо придется добавить колонку id1, которую сделать первичным ключом, а по id построить просто индекс. Не знаю прокатит ли такое.
|
|||
12
stopa85
31.08.23
✎
14:34
|
(10) У вас какой-то кастрированный explain.
Вот у меня какой (из заббикса табличка) explain select * from history where itemid = 42259 order by clock limit 20; QUERY PLAN ------------------------------------------------------------------------------------------- Limit (cost=0.43..73.34 rows=20 width=24) -> Index Scan using history_pkey on history (cost=0.43..53292.28 rows=14620 width=24) Index Cond: (itemid = 42259) (3 rows) |
|||
13
GANR
31.08.23
✎
14:54
|
(12) суть проста - scan using svjul_pkey вместо нужного мне индекса вот и всё
|
|||
14
H A D G E H O G s
31.08.23
✎
15:14
|
Нихера не понятно, но очень интересно.
Руки бы оторвать этим любителям сокращений. select * - вот причина. Поменяй на select INN |
|||
15
GANR
31.08.23
✎
15:21
|
(14) это мимо
|
|||
16
GANR
31.08.23
✎
15:22
|
Ответ в (9). Другой вопрос как элегантнее решить проблему
|
|||
17
H A D G E H O G s
31.08.23
✎
15:29
|
(15) Как скажешь
|
|||
18
H A D G E H O G s
31.08.23
✎
15:33
|
Если считаешь, что твоя сортировка волшебным образом заставляет использоваиь некластерный индекс - ну так выбери во временную таблицу, а потом досортируй как надо.
|
|||
19
H A D G E H O G s
31.08.23
✎
15:37
|
Скорее всего ты просто прогрел кэш и запрос все также шарашит по кластерному индексу, ведь ему нужны остальные поля для select *, которых нет в некластерном и за которыми надо сходить по ridlookup. Да, limit скорее всего позволит это сделать только не более 20 раз, но так ли умен оптимизатор pg.
|
|||
20
GANR
31.08.23
✎
15:37
|
(18) запрос менять нельзя в том то и проблема
|
|||
21
H A D G E H O G s
31.08.23
✎
15:40
|
(20) конкурсы все интереснее. Ну ты план запроса то хоть собери для
1) ORDER BY created 2) Select inn Чтобы понимать картину |
|||
22
H A D G E H O G s
31.08.23
✎
15:41
|
(20) добавь в твой индекс все поля запроса по include
|
|||
23
H A D G E H O G s
31.08.23
✎
15:41
|
**все поля таблицы
|
|||
24
Garykom
гуру
31.08.23
✎
16:30
|
Каким местом извлечение из jsonb в текст, затем ltrim а затем еще и ilike
Может работать быстро? |
|||
25
Kesim
31.08.23
✎
16:36
|
(0) проблема в том что не по-русски написано)))
|
|||
26
GANR
31.08.23
✎
17:36
|
(24) Может, это ведь GIN индекс как раз для ilike. Ну а если бы ilike не было то и btree сгодился бы.
|
|||
27
Garykom
гуру
31.08.23
✎
17:43
|
>CREATE INDEX IF NOT EXISTS idx_gin_svjul_ltrim_inn_id ON svjul USING gin (ltrim(data ->> 'INN') gin_trgm_ops, id);
не нравится мне что индекс по вычисляемому полю как sql поймет что один ltrim(data ->> 'INN' равен другому ltrim(data ->> 'INN' да еще для ilike ? |
|||
28
Garykom
гуру
31.08.23
✎
17:45
|
(27)+ имхо делай ты отдельную табличку с INN и используй ее
|
|||
29
GANR
31.08.23
✎
17:52
|
(27) Легко понимает, если я меняю первичный ключ с id на другую колонку. И запрос из 0 работает быстро. Вот только теперь выяснено, что приложение каким то боком подхватывает новый первичный ключ строит по нему другой order by и снова получается зависание. Получается замена первичного ключа не катит. Как-то статистику покрутить может можно??
|
|||
30
GANR
31.08.23
✎
17:52
|
(29) к (28)
|
|||
31
GANR
31.08.23
✎
17:55
|
(28) к сожалению запрос формирую не я, а стороннее приложение... так бы давно перекроил запрос и забыл как страшный сон
|
|||
32
Garykom
гуру
31.08.23
✎
17:55
|
а если убрать id?
CREATE INDEX IF NOT EXISTS idx_gin_svjul_ltrim_inn_id ON svjul USING gin (ltrim(data ->> 'INN') gin_trgm_ops); |
|||
33
Garykom
гуру
31.08.23
✎
18:04
|
(32)+ гм не понял а gin_trgm_ops это что?
|
|||
34
Garykom
гуру
31.08.23
✎
18:38
|
(33)+ понял указание на триграмный
|
|||
35
GANR
31.08.23
✎
22:41
|
(32) тогда он сможет ускорить запрос без order by id - не катит
(34) полнотекстовый мудреж |
|||
36
GANR
31.08.23
✎
22:41
|
(35) опечатка, наоборот НЕ сможет
|
|||
37
GANR
31.08.23
✎
22:43
|
Из за order by id
|
|||
38
Garykom
гуру
31.08.23
✎
23:10
|
сделай view
|
|||
39
Djelf
01.09.23
✎
07:47
|
А может попробовать убрать "USING gin"?
Вроде этот индекс не так работает, как хотелось бы (0) https://postgrespro.ru/docs/postgrespro/9.5/datatype-json#json-indexing |
|||
40
GANR
01.09.23
✎
11:33
|
(38) не пойдет - приложуха с view работать не сможет
(39) не пойдет - кроме gin с ilike не работет ничего Как ни странно, я добавил колонку id1, перекинул первичный ключ с id на id1, затем перекинул ключ обратно на id и удалил id1 - в итоге запрос начал подхватывать мой индекс gin вместо первичного ключа, каким образом мои манипуляции могли повлиять знает кто-нибудь? |
|||
41
Djelf
01.09.23
✎
11:51
|
(40) Хм, проверил онлайн запросом, ilike сработал без gin.
Откуда сведения? В документации нет таких ограничений https://postgrespro.ru/docs/postgresql/9.6/functions-matching |
|||
42
GANR
01.09.23
✎
12:05
|
(41) он сработал, но только на больших объемах то медленно будет, в нашем случае это = не работает
|
|||
43
GANR
01.09.23
✎
14:27
|
Удалось добиться ускорения поиска по ИНН вот такими заклинаниями:
CREATE INDEX IF NOT EXISTS idx_gin_svjul_ltrim_id_inn ON svjul USING gin (id, ltrim(data ->> 'INN') gin_trgm_ops); ALTER INDEX idx_gin_svjul_ltrim_id_inn ALTER COLUMN 2 SET STATISTICS 1000; ANALYZE svjul; |
|||
44
GANR
01.09.23
✎
14:29
|
(38) (39) (21) (10) (1) благодарю за содействие. Хотелось бы поподробнее до каких пор эта штука у меня проработать может ещё и если недолго то как продлить?
|
|||
45
ansh15
01.09.23
✎
16:57
|
(44) Многопоточность как-нибудь применяется? Скажем, max_parallel_workers_per_gather=6
и в плане запроса Workers Planned: 6 Workers Launched: 6 -> Parallel Seq Scan и т.д. |
|||
46
GANR
01.09.23
✎
17:57
|
(45) Даже и не знаю. А как это на план запроса влияет?
|
|||
47
ansh15
01.09.23
✎
19:05
|
(46) Здесь есть примеры https://habr.com/ru/articles/305662/
Статья старенькая, но все же.. |
Форум | Правила | Описание | Объявления | Секции | Поиск | Книга знаний | Вики-миста |