java – 使用Hibernate管理MySQL分区

我们目前正在评估将MySQL分区用于我们的小型应用程序.应用程序基本上只位于消息队列的末尾,并使用Hibernate将我们的API请求(包括时间戳)记录到数据库中.不幸的是,我们收到了很多请求,查询数据库变得非常慢.我们想要...

我们目前正在评估将MySQL分区用于我们的小型应用程序.应用程序基本上只位于消息队列的末尾,并使用Hibernate将我们的API请求(包括时间戳)记录到数据库中.不幸的是,我们收到了很多请求,查询数据库变得非常慢.

我们想要做的是按时间戳(每月)对表进行分区,因为我们的常规查询模式类似于“在时间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

缓慢的查询(显然是由Doctrine生成):

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

在解析查询MySQL时,它说它正在使用apikey_timestamp_rows_idx索引.

一个小上下文:对于给定的API密钥,我们想知道有多少行请求>每个用户在给定时间段内发送的0.

该表目前有大约22亿行.

解决方法:

我不知道任何处理表分区的hibernate API.

我认为你别无选择,只能使用原生SQL.您可以在Java代码中使用SQL(我认为您建议使用)或将其放在存储过程中.

您可以使用Java或MySQL安排此操作.如果您在应用服务器中使用某个线程执行此操作,则会遇到每个应用服务器都有这样的预定作业的问题.这使得难以控制作业实际执行的频率.在这种情况下,这可能不是什么大问题,因为与分区相关的查询不是很重.

您也可以在MySQL中安排它(见How to schedule a MySQL query?).此选项可以提供对作业的更多可见性(例如,对您的DBA),并且更易于管理和监控.

本文标题为:java – 使用Hibernate管理MySQL分区

基础教程推荐