【发布时间】:2015-02-17 19:03:56
【问题描述】:
我有一个带分区的简单表(范围分区数为 10)
CREATE TABLE `document_key_points` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`key_point_id` int(11) DEFAULT NULL,
`data_date` date DEFAULT NULL,
`data_decimal` decimal(22,6) DEFAULT '0.000000',
`data_boolean` tinyint(1) DEFAULT NULL,
`document_id` int(11) DEFAULT NULL,
`data_integer` int(11) DEFAULT NULL,
`is_deleted` tinyint(1) DEFAULT '0',
`data_string` text,
`created_at` datetime DEFAULT NULL,
`updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`,`key_point_id`),
KEY `data_integer` (`data_integer`),
KEY `document_id` (`document_id`),
KEY `key_point_id` (`key_point_id`),
KEY `data_boolean` (`data_boolean`),
KEY `data_decimal` (`data_decimal`),
KEY `data_date` (`data_date`),
) ENGINE=InnoDB DEFAULT CHARSET=utf8
PARTITION BY RANGE (key_point_id) (
PARTITION p0 VALUES LESS THAN (163),
PARTITION p1 VALUES LESS THAN (271),
PARTITION p2 VALUES LESS THAN (364),
PARTITION p3 VALUES LESS THAN (370),
PARTITION p4 VALUES LESS THAN (378),
PARTITION p5 VALUES LESS THAN (384),
PARTITION p6 VALUES LESS THAN (397),
PARTITION p7 VALUES LESS THAN (460),
PARTITION p8 VALUES LESS THAN (487),
PARTITION p9 VALUES LESS THAN (MAXVALUE));
我正在运行一个简单的选择查询,执行需要很长时间(12 秒)
select data_string,document_id from document_key_points cd where key_point_id =12
解释
+----+-------------+-------+------+---------------+---------+---------+-------+---------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+---------------+----------+---------+-------+---------+-------------+
| 1 | SIMPLE | cd | ref | key_pt_id | key_pt_id| 4 | const | 1957136 | Using where |
+----+-------------+-------+------+---------------+----------+---------+-------+---------+-------------+
我在这个表中有 5000 万行,目的是优化查询输出接近 1-2 秒, 什么方法可以帮助我优化此查询以达到 1-2 秒?
注意:相同的查询在 8 秒内运行,没有分区。
更新: 添加解释分区
+----+-------------+-------+------------+------+---------------+-----------+---------+-------+---------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------------+------+---------------+-----------+---------+-------+---------+-------------+
| 1 | SIMPLE | cd | p0 | ref | key_pt_id | key_pt_id | 4 | const | 1957136 | Using where |
+----+-------------+-------+------------+------+---------------+-----------+---------+-------+---------+-------------+
【问题讨论】:
-
这是在当前版本的 MySQL 上,比如 5.6 吗?
-
请解释为什么要对这个表进行分区。除了您尝试优化查询之外,还有什么推动它的吗?您在
data_string列中存储的数据的最大长度是多少?此查询返回多少行? -
您的查询似乎正在提取 GiB 左右的数据。在大约十秒钟内要处理很多位。有没有办法在不传输您的
data_string值的情况下处理此类查询?我之所以这么问,是因为这样的查询通常可以使用复合覆盖索引来优化。另外,分区不太可能有助于该表的查询性能。 -
您可以通过将
key_point_id索引更改为 (key_point_id, is_deleted) 来稍微改进一下。但我认为最好的办法是调查你需要这百万行来做什么。我不认为你会在一个单一的呐喊中显示它。不管它是什么,它可能被分页吗?如果是这样,可以稍后检索 data_string 吗?等等。 -
您需要能够在这几秒钟内管理 1GB 的硬件。不是最简单的事情。那个。
标签: mysql optimization query-optimization partitioning