|
Как оптимизировать запрос с большим количеством записей в таблице?
|
|||
---|---|---|---|
#18+
Существует таблица кодов, в ней в частности есть поля vendor_id, used и code_limit. Used обозначает, сколько раз выдавался код, code_limit - сколько максимум один код можно выдать, при "-1" бесконечно. vendor_id - это владелец кода (например, игра). В таблице имеется 13 млн записей, необходимо выдать первый неиспользованный код по определённому вендору. Собстсвенно, вот запрос: Код: sql 1.
Индекс есть на vendor_id, однако вот, что показывает explain analyze: Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11.
Во-первых, не используется индекс, во-вторых, это очень долго для казалось бы простого запроса. Ок, делаю индексы (vendor_id, used, code_limit), (vendor_id, code_limit, used) - не прокатывает. Перепробовал все шесть вариантов индексов по этим трём полям - результат ноль. Отписался здесь https://dba.stackexchange.com/questions/209521/how-to-involve-table-index-in-filtering-of-3-conditions?noredirect=1#comment410644_209521 Товарищ предложил сделать частичный индекс. Вот результат: Код: sql 1.
Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11.
И близко не индекс. Интуитивно предполагаю, что слабое место это used < limit. По нему либо индекс вобще работать не хочет, либо нужен какой-то очень хитрый индекс. Пробовал создать частичный индекс именно по этому условию: Код: sql 1.
Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9.
Тоже не использует индекс. насколько я понимаю, индексы хорошо работают с конкретными значениями, но проиндекировать отношение полей что-то не очень получается. Заметил щё вот такую вещ. Второй раз по тому же vendor_id запрос отрабатывает уже очень быстро: Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9.
Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9.
Однако, если чередовать vendor_id (1 -> 2 -> 1), то все запросы будут медленными. Собственно, вопрос один: как мне оптимизировать этот запрос? Ну и сопуствующие: существует ли индекс, который задействуется, если в условиии есть отношение полей, а не сравнения с константами? Почему при повторном запросе по тем же самым параметрам, запрос выполняется быстро? Если это кеширование, то по каким ключевым словам это гуглить? И как настроить такое кеширование на все значения vendor_id в моём случае, а не только на последнего, который был в запросе? ... |
|||
:
Нравится:
Не нравится:
|
|||
14.06.2018, 18:37 |
|
Как оптимизировать запрос с большим количеством записей в таблице?
|
|||
---|---|---|---|
#18+
Малахов Дмитрий, если размер таблицы сильно больше доступной под кэш памяти, то как ни крути - всю её в "голову" севера не вложишь. Будут выталкивания из кэша, будут физические чтения. Индексы полезны, если они селективны. Когда из таблицы выбирается, условно говоря, пол-таблицы (или пятая часть - как в вашем случае), то доступ по индексу будут заведомо хуже, чем полный скан таблицы (тут накладывается оверхед, связанный со спецификой доступа к данным по индексу). ... |
|||
:
Нравится:
Не нравится:
|
|||
14.06.2018, 18:43 |
|
Как оптимизировать запрос с большим количеством записей в таблице?
|
|||
---|---|---|---|
#18+
Малахов Дмитрий, а вы уверены, что вам нужен select * from, а не какое-то конкретное поле типа code? Вот и сделайте индекс включающий нужное поле в селекте. ... |
|||
:
Нравится:
Не нравится:
|
|||
14.06.2018, 18:45 |
|
Как оптимизировать запрос с большим количеством записей в таблице?
|
|||
---|---|---|---|
#18+
Ути ПутиМалахов Дмитрий, а вы уверены, что вам нужен select * from, а не какое-то конкретное поле типа code? Вот и сделайте индекс включающий нужное поле в селекте. include вроде в 11-й версии только появился.. ... |
|||
:
Нравится:
Не нравится:
|
|||
14.06.2018, 18:58 |
|
Как оптимизировать запрос с большим количеством записей в таблице?
|
|||
---|---|---|---|
#18+
Щукина Анна, авторесли размер таблицы сильно больше доступной под кэш памяти, то как ни крути - всю её в "голову" севера не вложишь мы специально взяли достаточно ёмкий сервак со 120 Гб оперативы, так что память вобще не проблема. Другое дело, что я пробовал игратся с параметрами кеширования, а именно shared_buffers стаивл в 10Гб, temp_buffers в 512 Мб (хотя, они вроде не причём тут), work_mem в 2 Гб, effective_cache_size 10Гб ставил. На этих параметрах пробовал выбирать vendor_id, у которого кодов не больше 1000. И всё равно, кешируется только последнее обращение. Вот почему я и спрашиваю про кеширование, я походу его просто не понимаю и надеюсь, что если пойму, оно мне поможет. ... |
|||
:
Нравится:
Не нравится:
|
|||
14.06.2018, 19:15 |
|
Как оптимизировать запрос с большим количеством записей в таблице?
|
|||
---|---|---|---|
#18+
Малахов Дмитрий, то есть, из 120 Гиг памяти на борту под буферный кэш PG выделили только 10 Гиг? Зачем тогда остальное? Если мне память не изменяет, то при более-менее больших значениях ОЗУ под буферный кэш рекомендуется выделять от 25% до 40%. ... |
|||
:
Нравится:
Не нравится:
|
|||
14.06.2018, 19:25 |
|
Как оптимизировать запрос с большим количеством записей в таблице?
|
|||
---|---|---|---|
#18+
Щукина Анна, тут три причины: - память нужна не только постгресу, но щё и редису, монге и нескольким другим сервисам. Взяли с запасом, чтобы не жалко было выделять; - это было просто тестовое значение, минимальное, которое в голову пришло; - я тестил на более слабом серваке. Если бы 10 Гб себя оправдали, на бою уже было бы все 60. 2000 записей для двух вендоров в 10 Гб явно должны были со свистом влезть, но не прокатило. ... |
|||
:
Нравится:
Не нравится:
|
|||
14.06.2018, 19:43 |
|
Как оптимизировать запрос с большим количеством записей в таблице?
|
|||
---|---|---|---|
#18+
Малахов Дмитрий- память нужна не только постгресу, но щё и редису, монге и нескольким другим сервисам. ... Вот и попробуйте решить задачу теми сервисами. Чтобы задарма ресурсы не жрали. По поводу запроса: Создайте индекс (vedor_id, <primary_key>). В самом запросе обязательно укажите ORDER BY <primary_key> (и далее ограничение limit) Результат отпишите. ... |
|||
:
Нравится:
Не нравится:
|
|||
14.06.2018, 20:52 |
|
Как оптимизировать запрос с большим количеством записей в таблице?
|
|||
---|---|---|---|
#18+
УткъУти ПутиМалахов Дмитрий, а вы уверены, что вам нужен select * from, а не какое-то конкретное поле типа code? Вот и сделайте индекс включающий нужное поле в селекте. include вроде в 11-й версии только появился.. Без инклуде, просто последним полем в индексе. В оракле тоже инклуде нет. ... |
|||
:
Нравится:
Не нравится:
|
|||
14.06.2018, 21:17 |
|
Как оптимизировать запрос с большим количеством записей в таблице?
|
|||
---|---|---|---|
#18+
ursido, авторВот и попробуйте решить задачу теми сервисами. Чтобы задарма ресурсы не жрали. Такие идеи тоже рассматриваются, однако для этого не две строчки кода надо будет написать. Да и хотелось бы запрос делать там, де данные лежат, а не писать костыли просто потому что много ресурсов подъехало. Не очень верится, что субд не умеет в производительность. авторСоздайте индекс (vedor_id, <primary_key>). В самом запросе обязательно укажите ORDER BY <primary_key> (и далее ограничение limit) Рабочий вариант! Спасибо. https://dba.stackexchange.com/questions/209521/how-to-involve-table-index-in-filtering-of-3-conditions - здесь мне тоже отписали рабочий вариант: Код: sql 1.
И затем при выборке тоже использовать abs: Код: sql 1. 2. 3. 4. 5. 6. 7. 8.
... |
|||
:
Нравится:
Не нравится:
|
|||
15.06.2018, 01:13 |
|
|
start [/forum/topic.php?fid=53&gotonew=1&tid=1995726]: |
0ms |
get settings: |
8ms |
get forum list: |
14ms |
check forum access: |
4ms |
check topic access: |
4ms |
track hit: |
46ms |
get topic data: |
9ms |
get first new msg: |
7ms |
get forum data: |
2ms |
get page messages: |
42ms |
get tp. blocked users: |
1ms |
others: | 371ms |
total: | 508ms |
0 / 0 |