【问题标题】:Performance impact of empty LIKE in a prepared statement准备好的语句中空 LIKE 的性能影响
【发布时间】:2013-09-25 16:57:28
【问题描述】:

我在files 表的name 列上设置了一个GiST pg_trgm 索引。

预处理语句的简化查询如下所示:

SELECT * FROM files WHERE name LIKE $1;

$1 参数将由 % + 用户查询 + % 组成。由于输入也可能是一个空字符串,这可能会导致%%

“空”LIKE (%%) 是否会导致性能下降?在这种情况下我应该建立一个新的查询,还是没关系?

【问题讨论】:

标签: sql postgresql pattern-matching prepared-statement postgresql-performance


【解决方案1】:

Postgres 9.2 或更高版本通常足够聪明,可以意识到条件

WHERE name LIKE '%%'

不是选择性的,而是采用忽略 GiST 索引的顺序扫描 - 即使使用准备好的语句。不过,您确实会为无用的条件付出一点代价。

在 Postgres 9.1 或更早版本中,我将为特殊情况构建单独的查询。

比较9.19.29.3 版本手册中PREPARE 语句的注释 部分。

验证自己

准备语句并运行EXPLAIN ANALYZE进行测试:

PREPARE plan1 (text) AS
SELECT  * FROM file
WHERE   name LIKE $1;

EXPLAIN ANALYZE EXECUTE plan1('%123%');

EXPLAIN ANALYZE EXECUTE plan1('%%');

Plans are generally cached for the duration of the session.

替代查询

不管你运行的是什么版本,如果你总是执行全文搜索(通配符左右),这个查询对于准备好的语句应该更快:

SELECT * FROM files WHERE name LIKE <b>('%' || $1 || '%')</b>;

当然,在不添加通配符的情况下传递模式 (%)。这样一来,Postgres 就知道在规划时期望使用通配符括起来的模式。

->SQLfiddle demo.
注意空 LIKE 的顺序扫描以及两个计划之间的性能差异。
SQLfiddle 变化很大,具体取决于负载等。单次运行可能不可靠。更好地在您的环境中进行测试,并多次运行每个语句以使缓存饱和并消除噪音。

【讨论】:

  • 已经这样做了,但cost 似乎仍然略高于LIKE
  • 所以0.1 的成本似乎比LIKE 高,我想这可以忽略不计。
  • 前两个查询只有在name is not null时才相等。
  • name 在我的情况下总是不为空
  • @IgorRomanchenko:关于 NULL 案例,您是对的。我现在已经用更具体的信息完全重写了答案。
猜你喜欢
  • 1970-01-01
  • 2019-07-02
  • 1970-01-01
  • 2011-01-09
  • 2016-04-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多