postgres中大型数据库的索引

Posted

技术标签:

【中文标题】postgres中大型数据库的索引【英文标题】:indexes for large database in postgres 【发布时间】:2014-03-12 01:08:26 【问题描述】:

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

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

这是我的杜松子酒指数:

CREATE INDEX city_gin_idx_name
  ON city
  USING gin
  (to_tsvector('english'::regconfig, lower(name::text)));

查询性能:

“排序(成本=117553.00..118496.71行=377482宽度=50)(实际 时间=1719.660..1745.702 行=35185 循环=1)" " 排序键: (concat(name, ', ', state_name, ', ', country_name))" " 排序方法: 外部合并磁盘:2200kB" " -> 城市序列扫描 (成本=0.00..56777.75 行=377482 宽度=50)(实际 时间=0.392..1474.559 行=35185 循环=1)"" 过滤器: ((lower((name)::text) ~~ '%ed%'::text) 或 ((city_metaphone)::text = 'K'::text))" " 过滤器删除的行数:1851806" "总运行时间: 1764.036 毫秒"

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

【问题讨论】:

能否请您正确格式化执行计划(保留缩进)? (例如使用<pre> 标签)因为它不是真正可读的。或者上传到explain.depesz.com 【参考方案1】:

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

create index … on city using GIN (to_tsvector('english', name));
create index … on city (city_metaphone);

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

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

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

【讨论】:

感谢您的回复。我尝试使用三元组,性能也有了很大的提高。查询执行时间现在已从 1500 毫秒减少到约 300 毫秒。但我仍然需要改进它。这是我们可以为这种情况做的最好的事情还是我们可以进一步优化它?这是我使用的索引: CREATE INDEX trgm_idx ON city USING gin (name gin_trgm_ops);我的查询: SELECT * FROM "city" WHERE name % 'ed' OR city_metaphone = 'K' 试过pgtrgm页面上的“F.30.4.文本搜索集成”? 据我从文本搜索集成中了解到的是,我们可以将其用于全文搜索或轻微的拼写错误。我需要提供自动完成的索引,我将只有 2-3 个字符,并且需要为此搜索匹配的单词。我不确定它是否对这种情况有用。如果我错了,请纠正我。

以上是关于postgres中大型数据库的索引的主要内容,如果未能解决你的问题,请参考以下文章

您如何计算在大型 Postgresql 表上创建索引的时间?

使用 int8range 连接 2 个大型 postgres 表不能很好地扩展

在 FROM 子句中创建大型虚拟表

使用 Pandas 在 Python 中处理大型 SQL 查询?

大型网站核心技术

SQLite:即使有索引,大型数据库中的查询也非常慢