【问题标题】:How to partition MySQL table with two indexes如何使用两个索引对 MySQL 表进行分区
【发布时间】:2013-03-26 03:23:07
【问题描述】:

我有一个表 game_log,其中包含字段 idgame_id 和几个 varchar 字段。

id 是主键,game_id 是非唯一键。

有两个常见的查询:

SELECT * FROM game_log ORDER BY id DESC LIMIT 20
SELECT * FROM game_log WHERE game_id = <value> ORDER BY id DESC

该表很大(6.1GB 和 32M 行)。创新数据库。其中的行是随机添加的(每个查询一个)。此外,一些游戏正在被删除。

我需要减少磁盘 IO 并提高响应速度。

我应该使用key 还是range 分区?如果range,那么id 还是game_id?有什么理论吗?

【问题讨论】:

  • 使用分区,确保每个分区都适合innodb_buffer_pool_size以避免I/O分页

标签: mysql innodb partitioning database-partitioning


【解决方案1】:

使用按范围分区。

如果您按键分区,则您的两个示例查询都必须触及每个分区。

理论上,KEY 分区类似于 hash 分区,主键的连续值必然会存储在不同的分区中。通过查询一系列 id 值,您破坏了分区修剪。

演示:

CREATE TABLE `game_log` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `game_id` int(11) NOT NULL DEFAULT '0',
  `xyz` varchar(15) DEFAULT NULL,
  PRIMARY KEY (`id`,`game_id`)
) 
PARTITION BY KEY ()
PARTITIONS 13;

INSERT INTO game_log (game_id) VALUES (1), (2), (3), (4), (5), (6);

EXPLAIN PARTITIONS SELECT * FROM game_log ORDER BY id DESC LIMIT 3\G
           id: 1
  select_type: SIMPLE
        table: game_log
   partitions: p0,p1,p2,p3,p4,p5,p6,p7,p8,p9,p10,p11,p12

EXPLAIN PARTITIONS SELECT * FROM game_log WHERE game_id = 4 ORDER BY id DESC LIMIT 3\G
           id: 1
  select_type: SIMPLE
        table: game_log
   partitions: p0,p1,p2,p3,p4,p5,p6,p7,p8,p9,p10,p11,p12

然而,如果您在 game_id 上按范围进行分区,则至少在查询特定 game_id 时,您可以获得分区修剪以帮助您。但是您通过 id desc 对任何 game_id 顺序的查询仍然会触及每个分区。

CREATE TABLE `game_log` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `game_id` int(11) NOT NULL DEFAULT '0',
  `xyz` varchar(15) DEFAULT NULL,
  PRIMARY KEY (`id`,`game_id`)
)
PARTITION BY RANGE (game_id)
(PARTITION p1 VALUES LESS THAN (3),
 PARTITION p2 VALUES LESS THAN (6),
 PARTITION p3 VALUES LESS THAN MAXVALUE);

INSERT INTO game_log (game_id) VALUES (1), (2), (3), (4), (5), (6);

EXPLAIN PARTITIONS SELECT * FROM game_log ORDER BY id DESC LIMIT 3\G
           id: 1
  select_type: SIMPLE
        table: game_log
   partitions: p1,p2,p3

EXPLAIN PARTITIONS SELECT * FROM game_log WHERE game_id = 4 ORDER BY id DESC LIMIT 3\G
           id: 1
  select_type: SIMPLE
        table: game_log
   partitions: p2

【讨论】:

  • 非常感谢。我想我也可以在“id DESC LIMIT”查询中添加game_id &gt; [some game id from the last partition]
  • 嗯,这对我来说很奇怪:PRIMARY KEY (id, game_id),虽然需要。我还需要为game_id 使用单独的非唯一密钥吗?
  • 是的,在 game_id 上有一个单独的索引会很有帮助。尝试使用 EXPLAIN 分析查询,如我所示,在 game_id 上创建额外索引之前和之后,您会看到它确实使用了索引。 (使用测试数据库执行此操作,而不是使用 6 GB 生产系统。)
  • 我将game_id添加到主键的原因是在MySQL中,分区列必须是任何主键或唯一键的一部分。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-05-29
  • 2014-06-18
  • 2017-12-11
  • 2021-08-17
  • 2012-08-25
  • 1970-01-01
相关资源
最近更新 更多