LIKE查询的最佳Postgres文本索引?

时间:2016-03-09 00:54:34

标签: sql postgresql indexing sql-like gin

使用Postgres 9.5,我有一个表addresses

CREATE TABLE addresses (
    id        integer PRIMARY KEY,
    address   text
);

在那张表中我有750万行。例如:

1, "1600 Pennsylvania Avenue NW, Washington, DC, 20500"

我在我的应用程序中使用此表进行自动搜索搜索,因此我需要使用此类查询:

SELECT * FROM addresses WHERE address LIKE '123 Main St%';

我创建了这个索引:

CREATE INDEX address_idx ON addresses (address);

但问题是它耗时约1秒,这太慢了。

这是查询计划:

EXPLAIN SELECT * FROM addresses WHERE address LIKE '123 Main St%';
----
Seq Scan on addresses  (cost=0.00..161309.76 rows=740 width=41)
  Filter: (address ~~ '123 Main St%'::text)

我尝试创建了几种类型的gin索引,但它们要么没有效果,要么使查询速度变慢。我不确定我是否正确使用它们。

有关如何创建针对此类查询优化的索引的任何想法?

修改

到目前为止,找到的最佳解决方案是使用文本范围扫描:

SELECT *
FROM addresses
WHERE address >= '123 Main St' AND
      address <= concat('123 Main St', 'z');

2 个答案:

答案 0 :(得分:4)

这是对between方法的详细说明,对评论来说太长了。

如果您使用的是标准ASCII字符,则可以使用代字号:

SELECT *
FROM addresses
WHERE address >= '123 Main St' AND
      address <= concat('123 Main St', '~');

Tilde的ASCII值比其他字符大。

我注意到Postgres也应该使用LIKE查询的索引。我的猜测是问题与类型的兼容性有关。也许如果您将模式转换为varchar(),Postgres将使用索引。

答案 1 :(得分:3)

你可以尝试三件事:

  1. 如果您的数据库已开启C&#39;语言环境(您可以在\l提示符下使用psql查看),然后常规Btree索引应有助于优化LIKE 'abc%'类型的查询。
  2. 如果没有,您可以在创建Btree索引时尝试使用合适的运算符类。对于例如CREATE INDEX tbl_col_text_pattern_ops_idx ON tbl(col text_pattern_ops);
  3. 如果这不起作用,您也可以尝试使用GiST / GIN,更详细的内容here
  4. 如果您想了解更多信息,请阅读Erwin的StackOverflow回复here,其中详细说明了Postgres索引与LIKE / ILIKE的不同之处。< / p>