【发布时间】:2012-05-31 06:38:43
【问题描述】:
我们有一个如下所示的 MySQL 表(删除了无关紧要的列):
CREATE TABLE `my_data` (
`auto_id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`created_ts` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_ts` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
`data_txt` varchar(256) CHARACTER SET utf8 NOT NULL,
`issued_ts` timestamp NULL DEFAULT NULL,
`account_id` int(11) NOT NULL,
PRIMARY KEY (`auto_id`),
KEY `account_issued_idx` (`account_id`,`issued_ts`),
KEY `account_issued_created_idx` (`account_id`,`issued_ts`,`created_ts`),
KEY `account_created_idx` (`account_id`,`created_ts`),
KEY `issued_idx` (`issued_ts`)
) ENGINE=InnoDB;
我们在表中有大约 900M 行,其中一个 account_id 占这些行的 65% 以上。我被要求为 created_ts 和 issue_ts 编写跨日期范围的查询,这些查询依赖于 account_id,它似乎对自动增量键具有 1:1 的功能依赖性。
典型的查询如下所示:
SELECT *
FROM my_data
WHERE account_id = 1 AND
created_ts > TIMESTAMP('2012-01-01') AND
created_ts <= TIMESTAMP('2012-01-21')
ORDER BY created_ts DESC LIMIT 100;
查询的解释表明:
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: my_data
type: range
possible_keys: account_issued_idx, account_issued_created_idx, account_created_idx,
key: account_issued_created_idx
key_len: 8
ref: NULL
rows: 365314721
Extra: Using where
问题是查询花费的时间太长并且最终被终止。我让它运行了几次,它导致数据库主机停机,因为操作系统 (Linux) 用完了交换空间。
我反复研究过这个问题,并尝试将查询分解为不相关的子查询、强制索引、使用显式 SELECT 子句并限制日期范围的窗口,但结果是一样的:差性能(太慢)和对主机的负担太重(总是死)。
我的问题是:
是否可以制定查询以将数据划分为日期范围并在实时调用中可接受地执行? (
为了获得我被要求获得的性能,我是否缺少或可能有帮助的优化?
欢迎任何其他建议、提示或想法。
谢谢
【问题讨论】:
-
去掉Order by子句后检查性能。