【问题标题】:not using index in where clause在 where 子句中不使用索引
【发布时间】:2013-07-06 18:26:30
【问题描述】:
如果我在 where 子句中有以下内容:
( approps_precio * moneda_valor BETWEEN 2000 AND 6000)
它不使用 idx_appprops_precio 索引。
但是
( approps_precio BETWEEN 2000 AND 6000)
做得很好。
有没有办法添加*操作仍然使用索引?
提前致谢。
【问题讨论】:
-
您是否考虑将产品approps_precio * moneda_valor 存储在它自己的(n 索引)列中?您可以使用triggers 来确保其值与基础列保持一致。
标签:
mysql
indexing
where
clause
【解决方案1】:
moneda_valor 是常量吗?如果没有,当您查找 appprops_precio 乘以 moneda_valor 的值时,approps_precio 上的索引将毫无用处。
【解决方案2】:
我一直在寻找一些官方文档来支持 Paul DuBois(尽管是 MySQL 文档团队的成员)在他的书 @987654321 的第五章“查询优化”中所说的话@:
使索引列在比较表达式中独立。如果您在函数调用中使用列或作为算术表达式中更复杂术语的一部分,MySQL 不能使用索引,因为它必须为每一行计算表达式的值。有时这是不可避免的,但很多时候您可以重写查询以使索引列自行出现。
我能找到的最好的是内部手册中关于Optimizer Transpositions 的部分:
但是,MySQL 不支持存在算术的转置。因此:
WHERE 5 = -column1
不被视为:
WHERE column1 = -5
转换为 column = constant 形式的表达式是索引查找的理想选择。
在这种情况下,可以通过除以moneda_valor 重写过滤条件来利用approps_precio 上的索引:
WHERE approps_precio BETWEEN 2000/moneda_valor AND 6000/moneda_valor
请注意,MySQL 仍需要评估每条记录的划分,因此我不相信会节省多少。
【解决方案3】:
当 moneda_valor 为空时,* 操作使您的值变为 0,因此超出范围。所以你可以重写为:
approps_precio BETWEEN 2000 AND 6000 and moneda_valor IS NOT NULL