MySQL分区和行的自动移动

问题描述 投票:0回答:1

我有一个约6M行的表,每个查询提取大约20,000-30,000行索引优化。然而,由于很多人连续提取这些行(每30秒左右),该网站通常会为人们超时。

我最近将数据库迁移到具有大量RAM(每服务器512GB)的3服务器MySQL集群,性能没有太大提高。

我想知道分区是否是提高性能的最佳方式。由于我完全没有分区经验,我想我会问这里。

我的问题是,所有这些行都有一个列,其值为0,1,2或3。

是否有可能以某种方式将值为1的所有行放在一个分区上的某个列中,将所有行中的值为2放在另一个分区中的列中?它们会根据主表中更新的值自动移动吗?最重要的是,它可以帮助提高性能,因为它只需要通过在20,000-30,000而不是6,000,000中找到1行来查看

mysql partition
1个回答
1
投票

是的,MySQL支持分区。您可以很好地定义分区,例如:

CREATE TABLE MyTable (
  id INT AUTO_INCREMENT PRIMARY KEY,
  somestuff INT,
  otherstuff VARCHAR(100),
  KEY (somestuff)
) PARTITION BY HASH(id) PARTITIONS 4;

INSERT INTO MyTable () VALUES (), (), (), ();

您可以在此之后验证每个分区中有多少行:

SELECT PARTITION_NAME, TABLE_ROWS FROM INFORMATION_SCHEMA.PARTITIONS WHERE TABLE_NAME='MyTable';
+----------------+------------+
| PARTITION_NAME | TABLE_ROWS |
+----------------+------------+
| p0             |          1 |
| p1             |          1 |
| p2             |          1 |
| p3             |          1 |
+----------------+------------+

但是,当他们尝试在MySQL中使用分区时,有两件事会引起人们的注意:

首先,正如https://dev.mysql.com/doc/refman/5.7/en/partitioning-limitations-partitioning-keys-unique-keys.html所说:

表上的每个唯一键必须使用表的分区表达式中的每一列。

这意味着如果你想在上面的例子中通过somestuff进行分区,你就不能。这将使主键包含分区表达式中指定的列的要求失败。

ALTER TABLE MyTable PARTITION BY HASH(somestuff) PARTITIONS 4;
ERROR 1503 (HY000): A PRIMARY KEY must include all columns in the table's partitioning function

您可以通过从表中删除任何主键或唯一键约束来解决此问题,但这会使您遇到格式错误的表。

其次,只有当您可以利用partition pruning时,分区才会加快查询速度,并且仅当您的查询条件包含分区表达式中使用的列时才会发生这种情况。

mysql> EXPLAIN PARTITIONS SELECT * FROM MyTable WHERE SomeStuff = 3;
+----+-------------+---------+-------------+------+---------------+-----------+---------+-------+------+-------+
| id | select_type | table   | partitions  | type | possible_keys | key       | key_len | ref   | rows | Extra |
+----+-------------+---------+-------------+------+---------------+-----------+---------+-------+------+-------+
|  1 | SIMPLE      | MyTable | p0,p1,p2,p3 | ref  | somestuff     | somestuff | 5       | const |    4 | NULL  |
+----+-------------+---------+-------------+------+---------------+-----------+---------+-------+------+-------+

注意这说它需要扫描分区p0,p1,p2,p3--即整个表。没有分区修剪,因此没有性能提升,因为它没有减少检查的行数。

如果您在分区表达式中使用的列中搜索特定值,您可以看到MySQL能够减少它扫描的分区数:

mysql> EXPLAIN PARTITIONS SELECT * FROM MyTable WHERE id = 3;
+----+-------------+---------+------------+-------+---------------+---------+---------+-------+------+-------+
| id | select_type | table   | partitions | type  | possible_keys | key     | key_len | ref   | rows | Extra |
+----+-------------+---------+------------+-------+---------------+---------+---------+-------+------+-------+
|  1 | SIMPLE      | MyTable | p3         | const | PRIMARY       | PRIMARY | 4       | const |    1 | NULL  |
+----+-------------+---------+------------+-------+---------------+---------+---------+-------+------+-------+

在非常具体的情况下,分区可以提供很多帮助,但分区并不像大多数人想象的那样多样化。

在大多数情况下,最好在表中定义更具体的索引,以支持您需要运行的查询。

© www.soinside.com 2019 - 2024. All rights reserved.