我正在使用自定义排序在 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;
这里的“name”是类型varchar(255)
,total_play_count 是bigint
,不允许有空值。
当我这样查询表时:
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
用 simple替换,我会得到相同的结果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
一开始使用有点乐观,但如果有人有答案或解决方法,我会保持开放。