Странное поведение сортировки с столбцом bigint через индекс GiST в PostgreSQL

Я работаю над реализацией быстрого текстового поиска в PostgreSQL 12.6 (Ubuntu 20.04.2 VBox) с настраиваемой сортировкой, и я использую pg_trgm вместе с индексом GiST (btree_gist) для отсортированного вывода. Идея состоит в том, чтобы вернуть 5 лучших подходящих исполнителей, у которых больше всего воспроизведений. Индекс создается так:

      create index artist_name_gist_idx on artist 
  using gist ("name" gist_trgm_ops, total_play_count) where active = true;

"имя" здесь типа varchar(255) и total_play_count, нули не допускаются.

Когда я запрашиваю таблицу следующим образом:

      select id, name, total_play_count 
from artist 
where name ilike '%the do%' and active = true 
order by total_play_count <-> 40312 
limit 5;

Получаю правильный результат:

         id   |          name           | total_play_count 
--------+-------------------------+------------------
   1757 | The Doors               |             1863
 733226 | Damsel in the Dollhouse |             1095
   9758 | The Doobie Brothers     |             1036
 822805 | The Doubleclicks        |              580
   7236 | Slaughter and the Dogs  |              258

Я бы получил тот же результат, если бы заменил total_play_count <-> 40312 с простым total_play_count desc, но затем я получаю дополнительную операцию сортировки, которой хочу избежать. Число 40312 здесь - текущее максимальное значение этого столбца, а сама таблица содержит всего 1612297 строк.

Однако, поскольку total_play_count имеет тип bigint, я хотел сделать этот запрос более общим (и более быстрым) и использовать максимальное значение для bigint, чтобы мне не приходилось каждый раз запрашивать максимальное значение. Но когда я обновляю предложение ORDER BY с помощью total_play_count <-> 9223372036854775807, Я получаю следующий результат:

         id    |          name           | total_play_count 
---------+-------------------------+------------------
    1757 | The Doors               |             1863
  822805 | The Doubleclicks        |              580
    9758 | The Doobie Brothers     |             1036
  733226 | Damsel in the Dollhouse |             1095
 1380763 | Bruce Bawss The Don     |               10

Порядок здесь нарушен, и становится еще хуже, когда я пробую тот же подход на другой таблице, в которой намного больше строк. Нет отрицательных или слишком больших значений, поэтому переполнение не должно быть возможным. Результаты explain практически идентичны:

       Limit  (cost=0.41..6.13 rows=5 width=34)
   ->  Index Scan using artist_name_gist_idx on artist  (cost=0.41..184.44 rows=161 width=34)
         Index Cond: ((name)::text ~~* '%the do%'::text)
         Order By: (total_play_count <-> '9223372036854775807'::bigint)

В чем может быть проблема? Это ошибка с btree_gist, или я что-то упускаю? Я мог бы согласиться на запрос максимального значения, но меня беспокоит, что есть порог, который может быть достигнут в конечном итоге и прервет поиск, что было бы позором, поскольку я вполне доволен производительностью.


Обновлять:

Я пробовал использовать обычный целочисленный тип вместо bigint, а затем запрашивать с его верхней границей total_play_count <-> 2147483647. Вроде с ним такой проблемы нет. Возможно, используя bigint во-первых, был несколько оптимистичным, но я оставлю вопрос открытым на случай, если у кого-то найдется ответ или обходной путь.

0 ответов

Другие вопросы по тегам