我有一个包含大约 1 亿条记录的大表,其中包含字段和start_date
类型。我需要检查某个日期范围的重叠数量,比如在AND之间,所以我使用。end_date
DATE
2013-08-20
2013-08-30
SELECT COUNT(*) FROM myTable WHERE end_date >= '2013-08-20'
AND start_date <= '2013-08-30'
日期列被索引。重要的一点是,我正在搜索重叠的日期范围总是在未来,而表中记录的主要部分是过去(比如大约 97-99 百万)。那么,如果我添加一个列,这个查询会更快吗is_future - TINYINT
,所以,通过只检查这样的条件
SELECT COUNT(*) FROM myTable WHERE is_future = 1
AND end_date >= '2013-08-20' AND start_date <= '2013-08-30'
它将排除其余 9700 万条左右的记录,并仅检查其余 1-3 百万条记录的日期条件?
我使用 MySQL
谢谢
编辑
mysql 引擎是 innodb,但如果是 MyISAM,则意义重大
这是创建表
CREATE TABLE `orders` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`title`
`start_date` date DEFAULT NULL,
`end_date` date DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=24 DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
在@Robert Co 回答后编辑 2
对于这种情况,分区看起来是个好主意,但它不允许我基于is_future
字段创建分区,除非我将其定义为主键,否则我应该删除我的主主键 - id,这是我做不到的。所以,如果我将该字段定义为主键,那么是否有分区的含义,如果我按is_future
主键字段搜索,它会不会很快。
编辑 3 我需要使用它的实际查询是选择在该日期范围内有一些空闲表的餐厅
SELECT r.id, r.name, r.table_count
FROM restaurants r
LEFT JOIN orders o
ON r.id = o.restaurant_id
WHERE o.id IS NULL
OR (r.table_count > (SELECT COUNT(*)
FROM orders o2
WHERE o2.restaurant_id = r.id AND
end_date >= '2013-08-20' AND start_date <= '2013-08-30'
AND o2.status = 1
)
)
解决方案 经过大量研究和测试,在我的案例中计算行数的最快方法是再添加一个条件,即 start_date 大于当前日期(因为搜索的日期范围总是在未来)
SELECT COUNT(*) FROM myTable WHERE end_date >= '2013-09-01'
AND start_date >= '2013-08-20' AND start_date <= '2013-09-30'
还必须有一个索引 - 带有 start_date 和 end_date 字段(谢谢@symcbean)。结果,10m 行表的执行时间从 7 秒开始 - 变为 0.050 秒。
解决方案 2(@Robert Co)在这种情况下的分区也很有效!- 也许它比索引更好的解决方案。或者它们可以一起应用。
谢谢