1

我有一个包含大约 850 万行的 MySQL Innodb 表。表结构基本上是这样的:

CREATE TABLE `mydatatable` (
  `ext_data_id` int(10) unsigned NOT NULL,
  `datetime_utc` date NOT NULL DEFAULT '0000-00-00',
  `type` varchar(8) NOT NULL DEFAULT '',
  `value` decimal(6,2) DEFAULT NULL,
  PRIMARY KEY (`ext_data_id`,`datetime_utc`,`type`),
  KEY `datetime_utc` (`datetime_utc`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

每天晚上,我使用以下查询从该表中删除过期值:

delete from mydatatable where datetime_utc < '2013-09-23'

这个查询似乎没有使用 indizes,运行起来需要相当长的时间。但是,我也会在同一张表上获得并发更新和选择。然后这些被锁定,导致我的网站当时没有响应。

我正在寻找各种方法来加快此设置。我遇到了 MySQL 分区,我想知道这是否合适。我总是在这个表中添加和选择新数据并删除旧数据。我可以基于 MOD(DAYOFYEAR(datetime),4) 之类的东西创建分区。现在,当我删除时,我总是会从另一个分区中删除值,而不是我正在读取或写入的分区。

我会遇到这种设置锁定的情况吗?在我的情况下,分区会提高查询速度和可用性吗?或者我应该寻找另一种解决方案,如果是,是哪一种?

4

2 回答 2

3

从 MySQL 5.5 开始,您可以使用函数COLUMNS,这可以简化非整数列(例如 datetime_utc)的分区。

至于表现:

  • 删除分区是 LIST 和 RANGE 分区的恒定时间操作。速度相当于 aTRUNCATE TABLErm file,因此实际上与分区的大小无关。
  • 对分区SELECT表进行操作受益于分区修剪,因此您只能从与您的搜索条件匹配的分区中读取。这也可以加快范围扫描。

小费:

不要忘记添加一个“默认”分区,例如

    PARTITION the_last_one VALUES LESS THAN(MAXVALUE)

为了避免INSERT/UPDATE语句失败,因为没有找到要插入的分区。

于 2013-09-25T08:04:37.630 回答
1

绝对你在正确的轨道上。您应该在这里创建每日分区并将数据存储在其中,您的查询将得到彻底改变并像法拉利一样运行。还可以查看本地索引。同样对于分区,如果您以前的数据不会干扰,那么您可以保留或删除它不会有太大区别。实际上,您可以简单地删除分区,而不是删除。这也非常快。

于 2013-09-24T15:49:01.257 回答