java - 使用 Hibernate 管理 MySQL 分区

标签 java mysql database hibernate partitioning

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

我们想要做的是按时间戳(每月)对表进行分区,因为我们的常规查询模式类似于“在时间 A 和 B 之间获取某些请求”。如果 A 和 B 连续两个月,这在大多数情况下都是正确的,那么这只会命中两个分区。

由于必须手动创建 MySQL 的范围分区,我想将此维护任务添加到我们的 Java 应用程序中,使其可以自动完成。这个想法是这样的:

  1. 有一个定期运行的实用线程(使用 ScheduledExecutorService 或其他东西)
  2. 在线程中,检查是否有下个月的分区
  3. 如果没有,就创建

没关系,但我无法尝试使用 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

EXPLAIN 查询时,MySQL 表示它正在使用 apikey_timestamp_rows_idx 索引。

一点上下文:对于给定的 API key ,我们想知道每个用户在给定时间段内发送了多少个 rows > 0 的请求。

该表目前有大约 22 亿行。

最佳答案

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

我认为您别无选择,只能使用 native SQL。您可以在 Java 代码中包含 SQL(正如我认为您所建议的那样),也可以将其放在存储过程中。

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

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

关于java - 使用 Hibernate 管理 MySQL 分区,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33126550/

相关文章:

java - 带/不带参数的命名约定,导致混淆错误?

mysql - JPA、mysql中的简单加密(用户名-密码)

php - Mysqli从表错误获取值

java - Kryonet 客户端超时后断开连接

java - maven-exec-plugin 无缘无故抛出异常

mysql - 包含连接的触发器

mysql - 如何使用 Laravel 5.3 通过 SSL 连接到 MySQL 数据库

mysql - 如何用MySQL中以前的非零值替换零值?

mysql - 用于跟踪和分摊费用的数据库设计

java - 如何使用Java OpenCV