使用 'LIKE '%' 的准备语句或即时生成查询哪个更好

Which is better between prepared statement with 'LIKE '%' or generate query on the fly

我正在实现一个典型的列表 Rest 端点 /items,其中包含一些可选的过滤 URI 查询参数,例如 ?attr=val&attr2=val 等。

Rest 服务器由 Go/MySQL

支持

关于查询性能,我想知道创建一个使用 LIKE 语句的准备好的语句是否更好:

SELECT cols from items WHERE attr LIKE ? and attr2 LIKE ?;

并简单地将值设置为 '%' 到用户未填写的属性

或者根据给定的属性动态生成查询?

没有属性的例子:

SELECT cols from items;

具有一个属性的示例:

SELECT cols from items where attr LIKE 'val';

更一般地说,我想知道使用 LIKE '%' 是否会产生性能成本(考虑到在这些列上正确配置了索引)。如果与动态生成查询(解析等)的成本相比,这些性能成本在准备好的语句中是值得的。

注意:不同过滤属性的数量非常多,无法为每种可能的属性组合生成特定的准备语句。

查询时涉及三个部分。

  1. 正在解析查询。
  2. 根据查询结构和使用的参数值优化查询。
  3. 正在使用优化查询进行查询。

查询优化器在技术上可以将 LIKE '%' 优化为不使用 LIKE 的东西,但似乎 MySQL 没有这样做(但我不是 100%当然可以)。

对于布尔值,查询优化器会执行此类优化。

如果你这样做:

SELECT * FROM test WHERE (attr='val' OR TRUE) AND (attr2='val' OR FALSE);

结果查询将是:

SELECT * FROM test WHERE attr2='val';

因为 (attr='val' OR TRUE) 永远是 TRUE,而 OR FALSE 什么都不做。

所以你总是可以有这样的东西:

SELECT * FROM test WHERE (attr=@attr OR !@useAttr) AND (attr2=@attr2 OR !@useAttr2);

和enable/disable使用布尔值的相应过滤器的用法。

如果值为 null 如果未设置,则类似这样:

SELECT * FROM test WHERE (attr=? OR ISNULL(?)) AND (attr2=? OR ISNULL(?));

然后像这样调用查询 stmnt.execute(attr, attr, attr2, attr2)

我建议您根据提供的数据花点时间构建查询。也就是说,构造 WHERE 子句仅包含用户要搜索的项目。

这可能会或可能不会真正加快速度,但它确实可以帮助您考虑 UI 并可能导致更好的 UI 设计。

当一列可能是,比方说,0 或 NULL 并且它们表示相同的东西时,使用 OR 会影响性能。相反,重新考虑模式——选择 0 或 NULL,而不是两者,作为任何指标。

如果您倾向于 LIKE '%xyz%',请考虑 FULLTEXT 索引是否更合适(而且速度更快)。

(同时,@t.niese 很好地讨论了优化。)