powered by simpleCommunicator - 2.0.60     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / Поиск по составному индексу в WHERE и ORDER BY
16 сообщений из 16, страница 1 из 1
Поиск по составному индексу в WHERE и ORDER BY
    #33880939
Предположим, есть таблица tbl с колонками f и b.

Рассмотрим запрос:
Код:
1.
2.
3.
4.
5.
SELECT *
FROM tbl
WHERE f=1
ORDER BY b
LIMIT 500


Если в таблице tbl запросу WHERE удовлетворяют подавляющее большинство записей (поле f - некоторый флаг, значение 1 которого говорит об активности записи, а 0 - о том, что запись архивна), то скорость работы приведенного запроса резко замедляется.

Пробовал создавать индексы по f, по b, по совокупности f и b. Ничего не помогает. Удаляем "WHERE f=1" - все начинает работать мгновенно, убираем "ORDER BY b" - то же самое. А вместе - жуткие тормоза (в таблице сотни тысяч записей). EXPLAIN ANALYSE показывает, что вначале он производит фильтрацию по f, а затем - сортировку по b. Естественно, надо делать наоборот: сортировку по b, а уж потом - фильтрацию по f.

Если бы PG был достаточно умен, чтобы сообразить использовать составной индекс (f, b) при таком запросе, проблем бы не было. Вопрос - можно ли все же как-то его заставить это сделать?
...
Рейтинг: 0 / 0
Поиск по составному индексу в WHERE и ORDER BY
    #33881021
фффф
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
VACUUM ANALYZE выполнялся? Какая версия постгреса? Можно результат EXPLAIN ANALYZE увидеть?

По-идее индекс (f,b) должен использоваться. Кстати в версии 8.1 при отключенном enable_bitmapscan план иногда бывает лучше - похоже что оптимизатор действительно тупит и делает bitmap scan вместо index scan там где не нужно. Из-за этого стоимость использования составного индекса оказывается выше чем простого.

И если активных записей немного, то не факт, что выгодней скан индекса по b, а затем фильтрация по f - ведь для этого надо все записи просматривать. В этом случае вместо индекса (f, b) выгоднее сделать
Код: plaintext
create index tbl_id_active on tbl(b) where f= 1 
...
Рейтинг: 0 / 0
Поиск по составному индексу в WHERE и ORDER BY
    #33881025
Владимор Конев
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Сдается мне, ты неправильно понимаешь логику работы сервера. :)
Есть определенная последовательность выполнения запроса, и все сервера (в том числе и PostgreSQL) выполняют запросы именно в такой последовательности, ибо это - стандарт.
И последовательность такова:
1) Формируется множество данных по таблицам и наборам данных, указанных во фразе FROM.
2) Накладываются ограничения из фразы WHERE на полученной множество.
3) Если указана группировка - производится группировка
4) Если указано условие фильтрации на результат группировки (фраза HAVING) - выполняется фильтрация.
5) Выполняется сортировка полученного итогового множества
6) И только после всего вышесказанного накладываются такие специфические вещи, как LIMIT / TOP N / FIRST N.

Поэтому сервер ну никак не может сделать вначале сортировку, а потом фильтрацию результата.

Но тебе никто не мешает его обмануть ;):
Код: plaintext
1.
2.
3.
4.
SELECT *
FROM tbl
 -- WHERE f=1 Условие фильтрации нафиг не нужно
ORDER BY f desc /*вначале записи с f = 1, затем с f = 0*/, b
LIMIT  500 
Вот только индекс нужен составной и желательно удовлетворяющий условиям сортировки.
Правда не факт, что так оно будет работать значительно быстрее - ведь необходимость сортировать выборку по прежднему остается...

-----------------------------------------------------------------------------------------------------------------------------------------
З.Ы.
Неспешно ищу работу, согласен на переезд в Москву или Питер
...
Рейтинг: 0 / 0
Поиск по составному индексу в WHERE и ORDER BY
    #33881616
4321
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Владимор Конев Правда не факт, что так оно будет работать значительно быстрее - ведь необходимость сортировать выборку по прежднему остается...

не поясните следующий результат:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
/*
CREATE UNIQUE INDEX udx_comp_mdb_status_actual
  ON korzina
  USING btree
  (id_comp_buh, id_mdb, status)
  WHERE actual = -1;
*/
EXPLAIN ANALYZE
SELECT * from korzina 
WHERE actual=- 1 
ORDER BY id_comp_buh, id_mdb, status
LIMIT  1 ;
Код: plaintext
1.
2.
"Limit  (cost=0.00..0.95 rows=1 width=223) (actual time=0.019..0.021 rows=1 loops=1)"
"  ->  Index Scan using udx_comp_mdb_status_actual on korzina  (cost=0.00..46981.39 rows=49340 width=223) (actual time=0.014..0.014 rows=1 loops=1)"
"Total runtime: 0.082 ms"
т.е. кажется постгресу иногда удается наложить лимит не затрудняясь получением всего, что возвращает WHERE ? или я что-то не так понимаю?
...
Рейтинг: 0 / 0
Поиск по составному индексу в WHERE и ORDER BY
    #33881857
LeXa NalBat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Дмитрий КотеровПробовал создавать индексы по f, по b, по совокупности f и b. Ничего не помогает. EXPLAIN ANALYSE показывает, что вначале он производит фильтрацию по f, а затем - сортировку по b.То есть используется SeqScan? Если старая версия постгреса можно попробовать "ORDER BY f,b" при наличии индекса по совокупности полей (f,b). (Приводите выдачу explain, она легче читается.:)

Дмитрий КотеровЕсли бы PG был достаточно умен, чтобы сообразить использовать составной индекс (f, b) при таком запросе, проблем бы не было. Вопрос - можно ли все же как-то его заставить это сделать?На это ума у постгреса определенно должно хватить. :)

Владимор КоневЕсть определенная последовательность выполнения запроса, и все сервера (в том числе и PostgreSQL) выполняют запросы именно в такой последовательности, ибо это - стандарт.Надо смотреть на планы запросов, чтобы узнать какие именно шаги и в какой последовательности выполняются.

Владимор Конев1) Формируется множество данных по таблицам и наборам данных, указанных во фразе FROM.Скорее надо рассматривать обработку как поточную. "Множество данных формируется" лишь когда в плане присутствует что-то типа Materialize, Hash, Sort.

Владимор Конев2) Накладываются ограничения из фразы WHERE на полученной множество.Ограничения могут накладываться посредством Filter, IndexCond,.. - это разные вещи в плане эффективности. Здесь рассуждать надо более точными понятиями этапов выполнения запроса, которые показывает explain.

Владимор Конев
Код: plaintext
 -- WHERE f= 1  Условие фильтрации нафиг не нужно
Этот запрос может выдать неправильный результат. Условие where убирать нельзя.

Владимор Коневведь необходимость сортировать выборку по прежднему остается...При выполнении через IndexScan сортировка может исчезнуть.
...
Рейтинг: 0 / 0
Поиск по составному индексу в WHERE и ORDER BY
    #33882088
Владимор Конев
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
4321не поясните следующий результат:
...
т.е. кажется постгресу иногда удается наложить лимит не затрудняясь получением всего, что возвращает WHERE ? или я что-то не так понимаю?Сортировки нет потому, что условия сортировки (порядок полей и направление упорядочивания) совпадают с оными в индексе.
Поэтому PostgreSQL выбрал индекс скан и как заметил LeXa NalBat
LeXa NalBat При выполнении через IndexScan сортировка может исчезнуть.
Условие WHERE было опущено и заменено на все тот же индекс скан, так как само условие фильтрации данных опять же совпадает с определением индекса.
В итоге получили в чистом виде индекс скан + наложение ограничения на выборку посредством LIMIT, как вполне достаточными для получения правильного результата (индекс еще в добавок ко всему и уникальный).
По-моему так, но могу и ошибаться - я же с PostgreSQL не работаю...

Если где-то ошибаюсь - поправьте, буду рад.
...
Рейтинг: 0 / 0
Поиск по составному индексу в WHERE и ORDER BY
    #33882348
LeXa NalBat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Владимор КоневУсловие WHERE было опущено и заменено на все тот же индекс сканНельзя смешивать 1) конструкции sql-запроса (where), которые sql-сервер обязан выполнить и 2) план выполнения запроса (индекс скан), на который вы не можете гарантированно влиять.

Владимор Коневтак как само условие фильтрации данных опять же совпадает с определением индекса.В вашем примере индекс был безусловным. Паршиал-индекс where f=1 наверное не должен использоваться в запросе без where f=1.

Владимор КоневВ итоге получили в чистом виде индекс скан + наложение ограничения на выборку посредством LIMIT, как вполне достаточными для получения правильного результата (индекс еще в добавок ко всему и уникальный).
Код: plaintext
1.
2.
3.
4.
SELECT *
FROM tbl
 -- WHERE f=1 Условие фильтрации нафиг не нужно
ORDER BY f desc /*вначале записи с f = 1, затем с f = 0*/, b
LIMIT  500 
Результат будет неправильным, если в таблице менее 500 строк с f=1 и хотя бы одна строка с f=0.
...
Рейтинг: 0 / 0
Поиск по составному индексу в WHERE и ORDER BY
    #33883917
Владимор Конев
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
LeXa NalBat Владимор КоневУсловие WHERE было опущено и заменено на все тот же индекс сканНельзя смешивать 1) конструкции sql-запроса (where), которые sql-сервер обязан выполнить и 2) план выполнения запроса (индекс скан), на который вы не можете гарантированно влиять.

Владимор Коневтак как само условие фильтрации данных опять же совпадает с определением индекса.В вашем примере индекс был безусловным. Паршиал-индекс where f=1 наверное не должен использоваться в запросе без where f=1.

Владимор КоневВ итоге получили в чистом виде индекс скан + наложение ограничения на выборку посредством LIMIT, как вполне достаточными для получения правильного результата (индекс еще в добавок ко всему и уникальный).
Код: plaintext
1.
2.
3.
4.
SELECT *
FROM tbl
 -- WHERE f=1 Условие фильтрации нафиг не нужно
ORDER BY f desc /*вначале записи с f = 1, затем с f = 0*/, b
LIMIT  500 
Результат будет неправильным, если в таблице менее 500 строк с f=1 и хотя бы одна строка с f=0.Чего-то ты вообще все в кучу замешал... :)
Мой пост был всего лишь ответом на вопрос от 4321 , разъясняющим поведение сервера в отдельно взятой конкретной ситуации, которую продемонстрировал 4321. Не более того.
Всё остальное - лишь твои домыслы и додумки к моим словам. Ибо моё мнение по прежднему остается таким, как я его высказал в своем ответе автору топика . Единственное, что в ситуации, опиаснной 4321, этапы по наложению условий фильтрации + сортировка результата были выполнены ПРЕДВАРИТЕЛЬНО, НА МОМЕНТ СОЗДАНИЯ ИНДЕКСА. И сервер просто облегчил себе работу, заменив в эквивалентной ситуации часть шагов на результат предварительно проделанной работы (то есть заменив шаги 2 и 5 на скан индекса, так как эти самые 2-й и 5-й шаг УЖЕ БЫЛИ ВЫПОЛНЕНЫ сервером при создании соответствующего индекса)

Вот такого: Владимор КоневВ итоге получили в чистом виде индекс скан + наложение ограничения на выборку посредством LIMIT, как вполне достаточными для получения правильного результата (индекс еще в добавок ко всему и уникальный).
Код: plaintext
1.
2.
3.
4.
SELECT *
FROM tbl
 -- WHERE f=1 Условие фильтрации нафиг не нужно
ORDER BY f desc /*вначале записи с f = 1, затем с f = 0*/, b
LIMIT  500 
я вообще не говорил. Это было два совершенно разных ответа на два совершенно разных впороса. Если ты этого не заметил - то это проблемы твоей [не]внимательности.

Во всем том, что ты сказал есть лишь одно верное (но вплоне опровержимое) высказывание:
LeXa NalBatРезультат будет неправильным, если в таблице менее 500 строк с f=1 и хотя бы одна строка с f=0. НО!!! Никто не мешает тебе обмануть сервер дважды: вначале выполнить запрос в том виде что я написал, получить результат, а потом в обрамляющем (внешнем) запросе наложить дополнительно условие WHERE f = 1.
Таким образом запрос примет вид:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
SELECT *
  FROM (
          SELECT *
            FROM tbl
        -- WHERE f=1 Условие фильтрации нафиг не нужно
          ORDER BY f desc /*вначале записи с f = 1, затем с f = 0*/, b
          LIMIT  500 
       ) V
 WHERE V.F =  1 
Еще вопросы имеются???
...
Рейтинг: 0 / 0
Поиск по составному индексу в WHERE и ORDER BY
    #33884464
4321
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Владимор Конев Еще вопросы имеются???да их и сразу не было. попросту указали на вашу неточность в формулировке:
авторЕсть определенная последовательность выполнения запроса, и все сервера (в том числе и PostgreSQL) выполняют запросы именно в такой последовательности, ибо это - стандарт.
+многобуковвы забрали многобуков взад (или же начали выкручиваться - мол "тута рыбку заворачивали" и т.п. - что, в сущности, рояля не играет - это проблемы _вашей_ готовности отвечать за _ваши_ многобуков, а не чьей-то "(не)внимательности" ).

Т.е. в итоге все всем ястно, а кто и как хочет вихлядеть в своих собственных глазах - дело десятое.

надеюсь вопросов нет?
...
Рейтинг: 0 / 0
Поиск по составному индексу в WHERE и ORDER BY
    #33884493
Владимор Конев
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
4321надеюсь вопросов нет?Лично у меня 4321да их и сразу не было(с)

-----------------------------------------------------------------------------------------------------------------------------------------
З.Ы.
Неспешно ищу работу, согласен на переезд в Москву или Питер
...
Рейтинг: 0 / 0
Поиск по составному индексу в WHERE и ORDER BY
    #33884867
LeXa NalBat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Владимор КоневЧего-то ты вообще все в кучу замешал... :)Я подумал, что ваши слова "Условие WHERE было опущено и заменено на все тот же индекс скан, так как само условие фильтрации данных опять же совпадает с определением индекса. В итоге получили в чистом виде индекс скан + наложение ограничения на выборку посредством LIMIT, как вполне достаточными для получения правильного результата (индекс еще в добавок ко всему и уникальный)" относятся к предложенному вами запросу с "-- WHERE f=1 Условие фильтрации нафиг не нужно".

Владимор КоневНикто не мешает тебе обмануть сервер дважды: вначале выполнить запрос в том виде что я написал, получить результат, а потом в обрамляющем (внешнем) запросе наложить дополнительно условие WHERE f = 1.
Таким образом запрос примет вид:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
SELECT *
  FROM (
          SELECT *
            FROM tbl
        -- WHERE f=1 Условие фильтрации нафиг не нужно
          ORDER BY f desc /*вначале записи с f = 1, затем с f = 0*/, b
          LIMIT  500 
       ) V
 WHERE V.F =  1 
Такой запрос может выдать неправильный результат, потому что во внешнем подзапросе отсутствует "order by".
...
Рейтинг: 0 / 0
Поиск по составному индексу в WHERE и ORDER BY
    #33884910
Владимор Конев
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
LeXa NalBatЯ подумал, что ваши слова ...
относятся к предложенному вами запросу с "-- WHERE f=1 Условие фильтрации нафиг не нужно".Я так и понял ;)

LeXa NalBatТакой запрос может выдать неправильный результат, потому что во внешнем подзапросе отсутствует "order by".А зачем он там?

Только для формальности? Ну добавь, лишним не будет...

Хотя, опять же , не зная особенностей поведения PostgreSQL при выполнении запросов из derived-таблиц, лучше таки поставить ORDER BY во внешнем запросе, а то вдруг серверу вздумается пересортировать данные перед тем, как он их начнет обрабатывать внешним запросом...
...
Рейтинг: 0 / 0
Поиск по составному индексу в WHERE и ORDER BY
    #33885049
LeXa NalBat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Владимор Конев LeXa NalBatТакой запрос может выдать неправильный результат, потому что во внешнем подзапросе отсутствует "order by".А зачем он там?

Только для формальности?

Хотя, опять же , не зная особенностей поведения PostgreSQL при выполнении запросов из derived-таблиц, лучше таки поставить ORDER BY во внешнем запросе, а то вдруг серверу вздумается пересортировать данные перед тем, как он их начнет обрабатывать внешним запросом...Вот вот, именно для этого. И даже зная особенности сегодняшнего поведения постгреса нельзя гарантировать, что в будущей версии он не захочет сделать какой-нибудь BitMapFilter или SuperPuperAction, при котором потеряется сортировка. Также существуют другие СУБД, в большинстве которых этот правильный запрос с "order by" будет работать одинаково верно.

Владимор КоневНу добавь, лишним не будет...Добавил.
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
SELECT *
  FROM (
          SELECT *
            FROM tbl
        -- WHERE f=1 Условие фильтрации нафиг не нужно
          ORDER BY f desc /*вначале записи с f = 1, затем с f = 0*/, b
          LIMIT  500 
       ) V
 WHERE V.F =  1 
 ORDER BY b
Такой запрос эквивалентен первоначальному. Однако в постгресе нельзя создать индекс по (f desc,b) поэтому к выбору плана IndexScan без сортировки (лишь это дает кардинальный выигрыш в производительности) такой запрос не приведет. :(
...
Рейтинг: 0 / 0
Поиск по составному индексу в WHERE и ORDER BY
    #33885097
4321
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
LeXa NalBat Однако в постгресе нельзя создать индекс по (f desc,b) без дополнительных усилий. (есть способ задать (создав его явно) свой способ сравнения в индексе, правда я не знаю способа указать этот способ сравнения в ORDER BY)
LeXa NalBatпоэтому к выбору плана IndexScan без сортировки (лишь это дает кардинальный выигрыш в производительности) такой запрос не приведет. :(для типов, для которых определена инверсия (-f), возможно таки извратиться (с одноверменной заменой f desc на (-f) и в ORDER BY и в индексе), но с оговорками о Null-абельности поля. Посему я взял -1 за True, и при фильтрации только активных записей (или всех) имею пользование составным индексом (есть и не условный индекс) в наиболее часто встречающихся конструкциях.
...
Рейтинг: 0 / 0
Поиск по составному индексу в WHERE и ORDER BY
    #33890921
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
SELECT *
FROM (
  SELECT * FROM tbl
  ORDER BY f<> 1 , b
  LIMIT  500 
) V
WHERE f= 1 
ORDER BY b
-- при наличии составного индекса по (f<>1, b)

В принципе, да, это решение. Спасибо.

Однако все же вопрос остается в силе: неужели Постгрес не может самостоятельно проделать такую трансформацию над запросом

Код: plaintext
1.
SELECT * FROM tbl WHERE f= 1  ORDER BY b

Правда, я не пробовал еще делать VACUUM ANALYZE (реальная база слишком большая, минут 30 будет выполняться), но - обязательно попробую. Потом напишу.
...
Рейтинг: 0 / 0
Поиск по составному индексу в WHERE и ORDER BY
    #33902449
LeXa NalBat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Дмитрий КотеровОднако все же вопрос остается в силе: неужели Постгрес не может самостоятельно проделать такую трансформацию над запросом
Код: plaintext
SELECT * FROM tbl WHERE f= 1  ORDER BY b
Постгрес может. Покажите explain plan.
...
Рейтинг: 0 / 0
16 сообщений из 16, страница 1 из 1
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / Поиск по составному индексу в WHERE и ORDER BY
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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