|
|
|
Производительность OFFSET
|
|||
|---|---|---|---|
|
#18+
Всем доброго дня. В документации указано ( http://www.postgresql.org/docs/9.3/static/queries-limit.html) "The rows skipped by an OFFSET clause still have to be computed inside the server; therefore a large OFFSET might be inefficient." У меня база под 5 млн., используется пагинация, чем целесообразно заменить OFFSET LIMIT для лучшей производительности? При больших значениях OFFSET жутко тормозит. Наверняка есть, какое то готовое решение. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 14.01.2014, 12:24:08 |
|
||
|
Производительность OFFSET
|
|||
|---|---|---|---|
|
#18+
qwwq, спасибо, но этот способ, как и другие способы, найденные в интернете не подходят. Ломаю голову уже 3 день. Проблема в том, что в таблице нет возможности использовать значения по порядку, чтобы заменить OFFSET и применять конструкции вида 'WHERE id >= 7041852 LIMIT 50' т.к. сначала в запросе происходит выборка нужных данных по категории. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 15.01.2014, 13:57:11 |
|
||
|
Производительность OFFSET
|
|||
|---|---|---|---|
|
#18+
slava7k, сначала в запросе происходит выборка нужных данных по категории, а затем выбрать 50 записей после 1000500? Не поделитесь постановочкой? Странно как-то звучит. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 15.01.2014, 14:03:04 |
|
||
|
Производительность OFFSET
|
|||
|---|---|---|---|
|
#18+
slava7kqwwq, спасибо, но этот способ, как и другие способы, найденные в интернете не подходят. Ломаю голову уже 3 день. Проблема в том, что в таблице нет возможности использовать значения по порядку, чтобы заменить OFFSET и применять конструкции вида 'WHERE id >= 7041852 LIMIT 50' т.к. сначала в запросе происходит выборка нужных данных по категории.при чём тут id OFFSET у вас подразумевает ORDER BY. где, если набор полей не является ключом, вы будете иметь "артефакты пагинации". (с поправкой на то, что NULL в полях допустим, и трактуется как одно из значений поля ключа). Поэтому всегда можно трансформировать ORDER BY {key-list} OFFSET xxx на WHERE {list {coalesce(keyN,'')}>=}. другое дело, что расписывать это (а для каждого набора фильтров у вас будет видимо свой order by) -- занятие тупое нетворческое и занудное. Скорее всего - динамическую компоновку придется пилить с коллекцией промежуточных значений полей ключа на клиенте. Ну и работать это сносно будет только при наличии индексов хотя бы по стартовым полям "ключа" (его вариантов). ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 15.01.2014, 14:11:12 |
|
||
|
Производительность OFFSET
|
|||
|---|---|---|---|
|
#18+
slava7k, PS отбор и "пагинация от достигнутого" у вас вполне могут лежать в одном WHERE Код: sql 1. 2. -- ибо оно, некоторым образом, т.с. "линейно не зависимо" ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 15.01.2014, 14:19:23 |
|
||
|
Производительность OFFSET
|
|||
|---|---|---|---|
|
#18+
qwwq, qwwq, у меня была такая мысль, только не могу понять, как можно получить "достигнутое"? Например, клиент запрашивает определенную категорию и вторую страницу. Делаем выборку сначала по категории, а потом как перескочить через первых 50 результатов? В одном запросе такое возможно? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 15.01.2014, 14:34:47 |
|
||
|
Производительность OFFSET
|
|||
|---|---|---|---|
|
#18+
slava7kqwwq, qwwq, у меня была такая мысль, только не могу понять, как можно получить "достигнутое"? Например, клиент запрашивает определенную категорию и вторую страницу. Делаем выборку сначала по категории, а потом как перескочить через первых 50 результатов? В одном запросе такое возможно? чтобы перескочить первые 50, надо отсчитать эти первые 50. чюдес не бывает. ускорение не в том,что вы не отсчитываете, а в том, что отслайсав сначала, вы кладете достигнутое в коллекцию ключей для Код: sql 1. а не делаете повторный отсчет при втором запросе offset-ом. и опять таки, это сносно работает, если конструкция Код: sql 1. хорошо слистывает по индексу. т.е. вся идея этой методы в том, чтобы достигнутые при фетче очередной страницы значения сложить в коллекцию, и использовать их при запросе следующей. если же вам по любому свистку сразу 100500-ю страницу хочется, то посмотрите на возможность вести таблицу "пагинирования" триггерами. Правда при множестве способов пагинирования скорее всего объём таблички будет запределен. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 15.01.2014, 14:51:23 |
|
||
|
Производительность OFFSET
|
|||
|---|---|---|---|
|
#18+
slava7kНапример, клиент запрашивает определенную категорию и вторую страницу.попробую пояснить. пользователь не может запросить "вторую страницу". он может запросить "начиная с достигнутого на предыдущей странице значения ключа". то есть параметр запроса не page=2, а start=123123. и мы на сервере делаем не запрос ORDER BY key LIMIT 50 OFFSET 50*(2-1), а запрос WHERE key>123123 ORDER BY key LIMIT 50. и рисуем пейджер не "1 2 3 4 5", а "first | next". ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 15.01.2014, 15:08:47 |
|
||
|
Производительность OFFSET
|
|||
|---|---|---|---|
|
#18+
qwwq, спасибо за разъяснения, вроде ясно (но пока мутно). Буду думать, что делать дальше. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 15.01.2014, 15:09:30 |
|
||
|
Производительность OFFSET
|
|||
|---|---|---|---|
|
#18+
LeXa NalBat, Такое решение точно не подходит, нужно сразу любую страницу запросить, даже готов пожертвовать производительностью, чтобы не более 1 сек. выходило. База содержит 5 млн. строк, порядка 90 категорий и 100к тегов, категории и теги хранятся полях ARRAY integer, поиск по ним с учетом индексов шустрый. Вот думаю, перепроектировать базу, какое лучшее решение будет? Может добавить памяти/проца чтобы на текущей базе в 1 сек. укладывалось? Оптимизировать настройки? (сейчас все дело крутится на дефолтной конфигурации после установки, 1 CPU, 1024 ram). ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 15.01.2014, 15:36:36 |
|
||
|
Производительность OFFSET
|
|||
|---|---|---|---|
|
#18+
slava7kнужно сразу любую страницу запроситьнапример гугл в линейке навигации по результатам поиска выводит ссылки только на первые десять страниц... :-O ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 15.01.2014, 15:46:24 |
|
||
|
Производительность OFFSET
|
|||
|---|---|---|---|
|
#18+
Нужно кешировать на фронт-енде ответ от сервера с первыми несколькими тыс. записей. Далее отдавать ответ из него. Или тоже самое, но в самой БД. Т.е. приходит запрос -> считаем хэшик (естественно, он не должен зависеть от номера запрашиваемой страницы), выполняем запрос -> сохраняем по хэшику рехультат в memcache, в самой БД, тупо в файл.. на какой-то TTL. Далее, при следующем запросе ищем сохранённую копию и если она не протухла, то юзаем для отдачи. Более труёвый вариант, как делают, например, в огромных соцсетях. Пишем специальный сервис вроде мемкеша, но который умеет не просто хранить блоб, но и инкрементально его апдейтить при поступлении новых данных. Во всём остальном всё как в предыдущем варианте. Можно было бы, конечно, обойтись как-нибудь через курсоры, но их трудно долго поддерживать валидными. Здесь алгоритм похожий, только кешируются не сами блобы, а коннект с СУБД + отктырый курсор с запросом. Очень геморно в реализации. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 19.01.2014, 01:10:34 |
|
||
|
|

start [/forum/topic.php?fid=53&fpage=133&tid=1998889]: |
0ms |
get settings: |
9ms |
get forum list: |
11ms |
check forum access: |
3ms |
check topic access: |
3ms |
track hit: |
63ms |
get topic data: |
8ms |
get forum data: |
2ms |
get page messages: |
36ms |
get tp. blocked users: |
1ms |
| others: | 229ms |
| total: | 365ms |

| 0 / 0 |
