我们目前正在评估MySQL分区对于我们的小应用程序的使用。应用程序基本上只是坐在消息队列的末尾,并使用Hibernate将我们的API请求(包括时间戳)记录到数据库中。不幸的是,我们收到很多请求,查询数据库变得非常缓慢。用Hibernate管理MySQL分区
我们想要做的是按时间戳(每月)对表格进行分区,因为我们的常规查询模式类似于“在时间A和B之间获得某些请求”。如果A和B连续两个月,这将主要是真实的,那么这将只是两个分区。
由于MySQL的范围分区必须手动创建,所以我想将这个维护任务添加到我们的Java应用程序中,它可以自动完成。我们的想法是这样的:
- 有定期执行的程序线程(使用
ScheduledExecutorService
或东西) - 在线程,检查是否有下个月
- 如果不分区,创建
这一切都很好,但我坚持尝试使用Hibernate获取MySQL的分区信息并创建分区。什么是最好的方式来做到这一点(我确定,如果这将是特定于MySQL)?
- 在Hibernate中是否有一个特定的API来获取表的MySQL分区信息,还可以创建分区?
- 我应该使用原始SQL(
SHOW CREATE TABLE ...
,ALTER TABLE ... ADD PARTITION
)并自己解析输出吗?
编辑:
表看起来像这样(我删除了一些的问题不相关列):
CREATE TABLE `request` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`apikey` varchar(32) NOT NULL,
`timestamp` datetime NOT NULL,
`rows` int(11) DEFAULT NULL,
`user_id` varchar(15) DEFAULT NULL
PRIMARY KEY (`id`),
KEY `apikey_idx` (`apikey`),
KEY `timestamp_idx` (`timestamp`),
KEY `apikey_timestamp_rows_idx` (`apikey`,`timestamp`,`rows`)
) ENGINE=InnoDB AUTO_INCREMENT=2190385211 DEFAULT CHARSET=utf8
,并(通过主义显然产生)慢查询:
SELECT
r0_.user_id AS user_id0, COUNT(r0_.id) AS sclr1
FROM
request r0_
WHERE
r0_.apikey = 'XXX' AND r0_.rows > 0 AND r0_.timestamp >= '2015-09-15 00:00:00' AND r0_.timestamp < '2015-10-15 00:00:00'
GROUP BY r0_.user_id
HAVING sclr1 > 0
ORDER BY sclr1 DESC
LIMIT 500
当EXPLAIN
ing查询MySQL表示它使用apikey_timestamp_rows_idx
索引。
稍微的上下文:我们想知道,对于给定的API密钥,每个用户在给定的时间段内发送的请求数量为rows > 0
。
该表目前约有22亿行。
我们来看看实际的查询和SHOW CREATE TABLE。分区不一定会比组合索引做得更好。 –
我在表格模式和查询中添加了我的问题 –