在对seperate question / answer的跟进中:我遇到的问题是,从成千上万的记录中确实使用了正确的索引。
前一段时间我自己想出了所提供的答案,并暂时实施了一段时间。现在数据库中有几千个事件(startdatetime和enddatetime列上的单独索引)但是由于查询本身,mysql interperter无法真正使用它们:
SELECT * FROM table WHERE start_date <= end_of_range
AND stop_date >= start_of_range
我认为这个问题很容易进一步优化吗? (必须通过40K记录来了解今天发生的事件(或任何其他范围)
我的问题:较大的应用程序如何解决这个问题?
以下评论后的更多信息: 查询:
EXPLAIN SELECT id
FROM event
WHERE startDatetime <= '2011-03-31 23:59:59'
AND endDatetime >= '2011-03-01 00:00:00'
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE event ALL startDatetime,endDatetime NULL NULL NULL 58331 Using where
换句话说:整个桌子?现在只是要清楚:查询不是定义慢,但它不使用任何索引......?
答案 0 :(得分:0)
您的逻辑是向后的,并且正在使服务器扫描太多记录以进行匹配。
请改为尝试:
SELECT * FROM table WHERE start_date >= start_of_range
AND stop_date <= end_of_range
这将利用索引,因为它可以快速定位start_date,然后只在索引中向前移动。它还可以快速定位你在stop_date上的索引,然后只需要向后扫描行。
答案 1 :(得分:0)
您可能正在描述一个非问题。
在你的测试查询中,mysql正在考虑使用2个索引(这就是你可以问的全部):它使用none,因为统计数据告诉它,与索引相比,表扫描会更有效。
我假设在您的示例中,您的测试查询没有足够的选择性来触发索引的使用(您的测试用例处理1个月的数据范围 - 满足条件的数据的百分比是多少?根据每个索引?)。
你唯一可以改进的是创建一个复合索引,因为我认为在你的例子中,mysql的index merge将无法帮助你。所以,要意识到这是一个不同的情况
startDateTime
上,另一个在endDateTime
与
相比(startDateTime, endDateTime)
此索引对于在某个范围内展开的事件最有用,并对endDateTime
应用其他条件。
您可能还考虑使用另一个索引:(endDateTime, startDateTime)
(对于查找范围内的事件并在startDateTime
上应用其他条件的查询,此索引应该最有帮助。)
您还可以阅读table scans,了解如何强制索引或修改某些服务器端变量可能会影响您的效果。
答案 2 :(得分:0)
让我们尝试将问题分成两部分,然后混合结果。
SELECT * FROM table t INNER JOIN (
SELECT id FROM table WHERE start_date <= end_of_range
) AS sd ON t.id = sd.id INNER JOIN (
SELECT id FROM table WHERE end_date >= start_of_range
) AS ed ON t.id = ed.id
我假设您在名为PRIMARY
的{{1}}上有一个table
密钥,这可能会使用id
和start_date
列上的索引,但是会使用临时表来合并结果。
如果事件表不断增长,您可能希望使用临时表而不是派生表。首先使用事件的end_date
填充临时表,然后在临时表的id
列上创建索引,最后进行连接。