我有一个像这样经常运行的php查询:
$query = 'SELECT * FROM work_orders '
.'WHERE '
. "((end_time >= ?"
. "AND start_time <= ?) "
. "OR (start_time <= ? "
. "AND end_time >= ? ) "
. "OR (start_time >= ? "
. "AND end_time <= ? )) ";
表格定义为:
CREATE TABLE IF NOT EXISTS `work_orders` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`work_order_number` varchar(32) COLLATE latin1_general_ci NOT NULL,
`start_time` datetime NOT NULL,
`end_time` datetime NOT NULL,
`client_name` varchar(128) COLLATE latin1_general_ci NOT NULL,
`location` varchar(128) COLLATE latin1_general_ci NOT NULL,
`note` varchar(255) COLLATE latin1_general_ci DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `note_idx` (`note`),
KEY `client_idx` (`client_name`),
KEY `location_idx` (`location`),
KEY `start_time_idx` (`start_time`),
KEY `end_time_idx` (`end_time`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_general_ci AUTO_INCREMENT=1 ;
我经常对如何创建索引感到困惑。这是一个读取繁重的表,其中包含大量数据搜索,这就是为什么我将每列编入索引,但到目前为止,最常运行的查询使用开始日期和结束日期的3种组合来确定工作单是否属于特定列日历范围。我应该像我目前那样单独使用start_time和end_time的索引,还是应该从这两个中创建复合键?是否有更好的方法来设置索引?我甚至应该使用InnoDB吗?我根本不使用交易。
答案 0 :(得分:0)
这个答案是双重的。首先,我会将索引设为:
KEY start_time_idx
(start_time
,end_time
)
但是(这是第二个问题):您的查询将无法使用任何索引。原因如下:
SELECT *
FROM work_orders
WHERE (
(end_time >= <some-date> AND start_time <= <some-date>)
OR
(end_time >= <some-date> AND start_time <= <some-date>)
OR
(end_time >= <some-date> AND start_time <= <some-date>)
)
一旦使用OR语句,就会有效地禁用OR语句中涉及的字段的索引使用。由于您的WHERE语句没有OR语句中没有涉及的其他字段,因此不会使用任何索引。
我认为这是在PHP脚本中执行的。你有权访问phpMyAdmin吗?然后尝试运行EXPLAIN前面的查询。它会给你一些提示。
如果表包含大量数据,您可能希望将此查询更改为3个查询,每个查询仅查询单个日期范围,然后在PHP中连接结果。
/卡斯滕