zir*_*iri 11 postgresql performance index full-text-search
我有这个查询:
SELECT *
FROM location
WHERE to_tsvector('simple',unaccent2("city"))
@@ to_tsquery('simple',unaccent2('wroclaw'))
order by displaycount
Run Code Online (Sandbox Code Playgroud)
我很高兴:
"Sort (cost=3842.56..3847.12 rows=1826 width=123) (actual time=1.915..2.084 rows=1307 loops=1)"
" Sort Key: displaycount"
" Sort Method: quicksort Memory: 206kB"
" -> Bitmap Heap Scan on location (cost=34.40..3743.64 rows=1826 width=123) (actual time=0.788..1.208 rows=1307 loops=1)"
" Recheck Cond: (to_tsvector('simple'::regconfig, unaccent2((city)::text)) @@ '''wroclaw'''::tsquery)"
" -> Bitmap Index Scan on location_lower_idx (cost=0.00..33.95 rows=1826 width=0) (actual time=0.760..0.760 rows=1307 loops=1)"
" Index Cond: (to_tsvector('simple'::regconfig, unaccent2((city)::text)) @@ '''wroclaw'''::tsquery)"
"Total runtime: 2.412 ms"
Run Code Online (Sandbox Code Playgroud)
但是当我添加 LIMIT 时,执行时间超过 2 秒:
SELECT *
FROM location
WHERE to_tsvector('simple',unaccent2("city"))
@@ to_tsquery('simple',unaccent2('wroclaw'))
order by displaycount
limit 20
Run Code Online (Sandbox Code Playgroud)
解释:
"Limit (cost=0.00..1167.59 rows=20 width=123) (actual time=2775.452..2775.643 rows=20 loops=1)"
" -> Index Scan using location_displaycount_index on location (cost=0.00..106601.25 rows=1826 width=123) (actual time=2775.448..2775.637 rows=20 loops=1)"
" Filter: (to_tsvector('simple'::regconfig, unaccent2((city)::text)) @@ '''wroclaw'''::tsquery)"
"Total runtime: 2775.693 ms"
Run Code Online (Sandbox Code Playgroud)
我认为这是 ORDER BY 和 LIMIT 的一些问题。如何强制 PostgreSQL 使用索引并在最后进行排序?
子查询没有帮助:
SELECT *
FROM (
SELECT *
FROM location
WHERE to_tsvector('simple',unaccent2("city"))
@@ to_tsquery('simple',unaccent2('wroclaw'))
order by displaycount
) t
LIMIT 20;
Run Code Online (Sandbox Code Playgroud)
或者:
SELECT *
FROM (
SELECT *
FROM location
WHERE to_tsvector('simple',unaccent2("city"))
@@ to_tsquery('simple',unaccent2('wroclaw'))
) t
order by displaycount
LIMIT 20;
Run Code Online (Sandbox Code Playgroud)
Erw*_*ter 13
我的猜测是这将解决您的查询:
SELECT *
FROM location
WHERE to_tsvector('simple',unaccent2(city))
@@ to_tsquery('simple',unaccent2('wroclaw'))
ORDER BY to_tsvector('simple',unaccent2(city))
@@ to_tsquery('simple',unaccent2('wroclaw')) DESC
,displaycount
LIMIT 20;
Run Code Online (Sandbox Code Playgroud)
我重复该WHERE条件作为ORDER BY子句的第一个元素——这在逻辑上是多余的,但应该让查询规划器不要假设根据索引处理行会更好location_displaycount_index——结果证明它要贵得多。
潜在的问题是查询计划器显然严重错误地判断了您的WHERE条件的选择性和/或成本。我只能推测这是为什么。
您是否正在运行autovacuum - 它也应该负责ANALYZE在您的桌子上运行?因此,您的表统计数据是最新的吗?如果您运行任何效果:
ANALYZE location;
Run Code Online (Sandbox Code Playgroud)
然后再试一次?
也可能是@@操作员的选择性被误判了。我认为由于逻辑原因很难估计。
如果我的查询不应该解决问题,并且通常要验证基础理论,请执行以下两件事之一:
临时删除索引 location_displaycount_index
通过运行暂时禁用基本索引扫描:
SET enable_indexscan = OFF;
Run Code Online (Sandbox Code Playgroud)后者侵入性较小,仅影响当前会话。它使方法bitmap heap scan和方法保持bitmap index scan开放,由更快的计划使用。
然后重新运行查询。
顺便说一句:如果理论是合理的,那么您的查询(正如您现在所拥有的)将在 FTS 条件下使用选择性较少的搜索词快得多 - 与您可能期望的相反。尝试一下。
| 归档时间: |
|
| 查看次数: |
4518 次 |
| 最近记录: |