有一个警告,以我的解决方案:
1)需要说明的该解决方案是,你必须使用针对该事件表中的MyISAM引擎。如果你不能使用MyISAM,那么这个解决方案将无法工作,因为只有MyISAM支持空间索引。
因此,假设上面是不是你的问题,下面应该工作,给你不错的表现:
该解决方案利用了MySQL的空间数据支持(见documentation here)。尽管可以将空间数据类型添加到各种存储引擎,但只有MyISAM才支持Spatial R-Tree索引(请参阅documentation here),这些索引是获得所需性能所必需的。另一个限制是空间数据类型仅适用于数字数据,因此您不能在基于字符串的范围查询中使用此技术。
我不会深入了解空间类型如何工作以及空间索引如何有用的理论细节,但您应该看看Jeremy Cole's explanation here关于如何使用空间数据类型和索引进行GeoIP查找。如果你需要原始的表现并且可以放弃一些准确性,那么看看他们提出的一些有用的观点和备选方案。
基本前提是我们可以采用开始/结束并使用它们中的两个创建四个不同的点,一个用于以xy网格为中心,以0,0为中心的矩形的每个角,然后快速完成查找空间索引以确定我们关心的特定时间点是否在矩形内。如前所述,请参阅Jeremy Cole的解释,以更全面地了解其工作原理。
在您的特定情况下,我们需要做到以下几点:
1)改变表是一个MyISAM表(注意你不应该这样做,除非你完全了解这种变化的后果比如缺少事务以及与MyISAM关联的表锁定行为)。
alter table events engine = MyISAM;
2)接下来我们添加一个新的列,它将保存空间数据。我们将使用多边形数据类型,因为我们需要能够保存一个完整的矩形。
alter table events add column time_poly polygon NOT NULL;
3)接下来我们填充数据的新列(请记住,该更新或插入到表事件将需要的任何进程得到修改,以确保它们也填充新列)。由于开始和结束范围是时间,所以我们需要使用unix_timestamp函数将它们转换为数字(有关它的工作原理,请参阅documentation here)。
update events set time_poly := LINESTRINGFROMWKB(LINESTRING(
POINT(unix_timestamp(start_time), -1),
POINT(unix_timestamp(end_time), -1),
POINT(unix_timestamp(end_time), 1),
POINT(unix_timestamp(start_time), 1),
POINT(unix_timestamp(start_time), -1)
));
4)接下来,我们空间索引添加到表中(如前面提到的,这将只对一个MyISAM表工作,并会产生错误“ERROR 1464(HY000):所使用的表型不支持SPATIAL索引“)。
5)接下来,您需要使用以下select来在查询数据时使用空间索引。
强制索引是让100%确定MySQL将使用该索引进行查找。如果一切顺利运行上述选择解释应该显示类似如下的内容:
mysql> explain SELECT *
-> FROM events force index (IXs_time_poly)
-> on MBRCONTAINS(events.time_poly, POINTFROMWKB(POINT(unix_timestamp('2009-02-18 16:27:12'), 0)));
+----+-------------+-------+-------+---------------+---------------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+-------+---------------+---------------+---------+------+------+-------------+
| 1 | SIMPLE | B | range | IXs_time_poly | IXs_time_poly | 32 | NULL | 1 | Using where |
+----+-------------+-------+-------+---------------+---------------+---------+------+------+-------------+
1 row in set (0.00 sec)
请参考杰里米·科尔的分析,有关此方法的性能优势细节,该条款进行比较。
让我知道如果您有任何问题。
感谢,
-Dipin
你的“start_time <= const以及ORDER BY start_time DESC LIMIT 1”是一个非常好的主意。由于start_date键似乎非常有效地使用,因此性能良好。剩下的答案应该发布在我发布的其他问题上! – daremon 2009-02-21 12:30:16
它也张贴在那里:) – Quassnoi 2009-02-21 23:18:37