mySQL分区和组合索引
我正在运行一个表,该表已经建立了6亿行,并且正在快速增长,这使得需要尽快运行的查询速度变慢。当前架构为:mySQL分区和组合索引,mysql,Mysql,我正在运行一个表,该表已经建立了6亿行,并且正在快速增长,这使得需要尽快运行的查询速度变慢。当前架构为: CREATE TABLE `user_history` ( `userId` int(11) NOT NULL, `asin` varchar(10) COLLATE utf8_unicode_ci NOT NULL, `dateSent` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, KEY `userId` (`userId`
CREATE TABLE `user_history` (
`userId` int(11) NOT NULL,
`asin` varchar(10) COLLATE utf8_unicode_ci NOT NULL,
`dateSent` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
KEY `userId` (`userId`,`asin`,`dateSent`),
KEY `dateSent` (`dateSent`,`asin`),
KEY `asin` (`asin`,`dateSent`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
我所读到的关于分区的所有内容都表明,这是按日期范围进行分区的主要候选对象。我们倾向于使用过去14天的数据,但客户不想删除旧数据。新架构如下所示:
CREATE TABLE `user_history_partitioned` (
`userId` int(11) NOT NULL,
`asin` varchar(10) COLLATE utf8_unicode_ci NOT NULL,
`dateSent` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`dateSent`,`asin`,`userId`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
PARTITION BY RANGE ( UNIX_TIMESTAMP(dateSent) ) (
PARTITION Apr2013 VALUES LESS THAN (UNIX_TIMESTAMP('2013-05-01')),
etc...
PARTITION Mar2014 VALUES LESS THAN (UNIX_TIMESTAMP('2014-04-01')),
PARTITION Apr2014 VALUES LESS THAN (UNIX_TIMESTAMP('2014-05-01')),
PARTITION May2014 VALUES LESS THAN (UNIX_TIMESTAMP('2014-06-01')),
PARTITION Future VALUES LESS THAN MAXVALUE);
未来分区的想法是因为在填充分区上运行的重组分区需要很长时间才能完成。所以未来总是空的,可以立即重新组织成新的分区。使用此表的其他查询已重新排序,仅使用主键,以减少表上的索引数
时间关键型查询适用于以下情况:
SELECT SQL_NO_CACHE *
FROM books B
WHERE (non-relevant stuff deleted)
AND NOT EXISTS
(
SELECT 1 FROM user_history H
WHERE
H.userId=$userId
AND H.asin=B.ASIN
AND dateSent > DATE_SUB(NOW(), INTERVAL 14 DAY)
)
AND (non-relevant stuff deleted)
LIMIT 1
因此,我们希望避免在过去14天内为同一用户选择重复项。现在返回时间小于0.1秒,这是可以的,但比当前模式上的返回时间要慢
对于新架构,内部选择已重新排序为:
SELECT 1 FROM user_history_partitioned H
WHERE dateSent > DATE_SUB(NOW(), INTERVAL 14 DAY)
AND H.asin=B.ASIN
AND H.userId=$userId
每个查询需要5分钟。我不明白为什么。其思想是,当前分区和索引应该在内存中,或者在一个月的某些时候也应该在上一个月,并且主索引包含WHERE子句。但从它所花费的时间来看,它可能在asin或userId上执行完整的表扫描。这很难从解释中识别,因为它是一个内部查询
我错过了什么?我是否需要asin的另一个组合索引,userID?若然,原因为何
谢谢
PS:尝试包装日期\u子。。。作为UNIX\u TIMESTAMPDATE\u SUB。。。以防万一,这是一个类型转换问题,但没有什么区别