查询:
EXPLAIN EXTENDED
SELECT *, u.user_id
FROM xgate_geoloc g
JOIN tig_users u
ON g.uid = u.uid
WHERE
-- corners selection:
( ( (lat BETWEEN COALESCE(?, lat) and COALESCE(?, lat))
AND (lat NOT BETWEEN COALESCE(?, lat) and COALESCE(?, lat))
)
OR ( (lon BETWEEN COALESCE(?, lon) and COALESCE(?, lon))
AND (lon NOT BETWEEN COALESCE(?, lon) and COALESCE(?, lon))
)
)
AND sex = COALESCE(?, sex)
AND language = COALESCE(?, language)
AND city = COALESCE(?, city)
AND province = COALESCE(?, province)
AND country = COALESCE(?, country)
AND time BETWEEN COALESCE(?, time) and COALESCE(?, time)
ORDER BY time DESC
- where 表达式中的“OR”对我应该使用的索引有任何影响吗?
- “时间”字段用于 where 和 order by。在这种情况下有什么办法可以建立索引吗?
- order by time desc - 降序;又一个无赖
感谢您的输入!
OR 很可能会影响索引的使用,因为它会阻碍索引查找。一般来说,“OR”对于 where 子句中的索引使用是“不好的”。
时间字段,当你使用它 DESC 时,将它放在按 DESC 顺序排序的索引中是明智的;
除此之外 - 我们需要更多信息来提供更准确/具体的建议
我认为停止索引
time
用于过滤的问题是使用了一个引用行的函数:COALESCE(?, time)
。我怀疑 mysql 的查询规划器不够聪明,无法简化
time BETWEEN COALESCE(?, time) and COALESCE(?, time)
为time BETWEEN <?1> AND <?1>
当两个相关参数都不是 NULL 时以及当一个参数为 NULL 时简化COALESCE(?, time)
为time
适当的参数为 NULL 时,然后进一步简化time BETWEEN time AND <something>
为time < <something>
或time BETWEEN <something> AND time
到time < <something>
尝试为每种情况准备单独的查询(两次都知道,开始为 NULL,结束为 NULL,并且都为 NULL),而不是尝试将其全部完成,以使查询计划者更轻松地完成该部分。