关于postgresql:postgres中大型数据库的索引

indexes for large database in postgres

我在postgres有一张表,有大约200万条记录。 我需要提供一些索引,以便为like %text%查询提供良好的性能。

我在某处读到Gin索引适用于%text%搜索并因此尝试了Gin和Gist索引,但不知道为什么没有这样的性能改进,并且Gin索引使用顺序扫描而不是堆扫描。

这是我的杜松子酒指数:

1
2
3
4
CREATE INDEX city_gin_idx_name
  ON city
  USING gin
  (to_tsvector('english'::regconfig, LOWER(name::text)));

查询性能:

"Sort (cost=117553.00..118496.71 rows=377482 width=50) (actual
time=1719.660..1745.702 rows=35185 loops=1)"" Sort Key:
(concat(name, ', ', state_name, ', ', country_name))"" Sort Method:
external merge Disk: 2200kB"" -> Seq Scan on city
(cost=0.00..56777.75 rows=377482 width=50) (actual
time=0.392..1474.559 rows=35185 loops=1)"" Filter:
((lower((name)::text) ~~ '%ed%'::text) OR ((city_metaphone)::text =
'K'::text))"" Rows Removed by Filter: 1851806""Total runtime:
1764.036 ms"

请告诉我这个要求的任何合适的索引。


您需要为该查询使用两个索引,并且需要在查询中使用完全相同的表达式来使用它们:

1
2
CREATE INDEXON city USING GIN (to_tsvector('english', name));
CREATE INDEXON city (city_metaphone);

请注意,在第一个索引中小写名称是无用的,因为to_tsvector在计算向量时无论如何都会忽略该大小写。

然后查询需要看起来像这样,你应该得到一个使用位图索引扫描的计划:

1
2
3
4
SELECT *
FROM city
WHERE city_metaphone = 'K'
   OR to_tsvector('english', name) @@ to_tsquery('english', 'Katmandu');

话虽如此,我认为你在这里使用全文是错误的。 特别是,您的'%ed%'表示您希望全文可以让您运行某种LIKE比较。

这不是它开箱即用的方式,但是三元组将使它以这种方式工作:

http://www.postgresql.org/docs/current/static/pgtrgm.html