天天看点

mysql表分区多表链接查询_MySql分区后创建索引加速单表查询和连表查询

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

本文链接:https://blog.csdn.net/konkon2012/article/details/96482548

为了加快查询,我们通常根据Where条件创建索引!那么分区后再创建索引,那就应该更快了!

我们依据订单表和订单商品表举例,先创建表结构:

CREATE TABLE `zstb_orders` (

`order_id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,

`org_id` INT(10) UNSIGNED NOT NULL,

`order_money` DECIMAL(6,2) UNSIGNED NOT NULL DEFAULT '0.00',

PRIMARY KEY (`order_id`,`org_id`),

KEY `order_id` (`order_id`)

) ENGINE=INNODB DEFAULT CHARSET=utf8;

CREATE TABLE `zstb_orders_goods` (

`order_id` INT(10) UNSIGNED NOT NULL DEFAULT '0',

`org_id` INT(10) UNSIGNED NOT NULL DEFAULT '0',

`goods_id` INT(10) UNSIGNED NOT NULL DEFAULT '0',

`goods_name` VARCHAR(20) DEFAULT '',

PRIMARY KEY (`order_id`,`org_id`,`goods_id`)

) ENGINE=INNODB DEFAULT CHARSET=utf8;

我们通过`org_id`来对两张表进行分区,脚本如下:

ALTER TABLE `zstb_orders` PARTITION BY RANGE(`org_id`) (

PARTITION p1 VALUES LESS THAN (100),

PARTITION p2 VALUES LESS THAN (200),

PARTITION p3 VALUES LESS THAN (300),

PARTITION p4 VALUES LESS THAN (400),

PARTITION p5 VALUES LESS THAN MAXVALUE

);

ALTER TABLE `zstb_orders_goods` PARTITION BY RANGE(`org_id`) (

PARTITION p1 VALUES LESS THAN (100),

PARTITION p2 VALUES LESS THAN (200),

PARTITION p3 VALUES LESS THAN (300),

PARTITION p4 VALUES LESS THAN (400),

PARTITION p5 VALUES LESS THAN MAXVALUE

);

至于为什么要使用'org_id'来进行分区,不是本文要讨论的问题,你可以根据你自身的需求使用其他字段来进行分区。

然后插入几条数据:

INSERT INTO `zstb_orders`(`order_id`, `org_id`, order_money) VALUES (1, 50, 200);

INSERT INTO `zstb_orders_goods`(`order_id`,`org_id`,`goods_id`,`goods_name`) VALUES (1, 50, 1, '酸奶');

INSERT INTO `zstb_orders_goods`(`order_id`,`org_id`,`goods_id`,`goods_name`) VALUES (1, 50, 2, '纯奶');

INSERT INTO `zstb_orders`(`order_id`, `org_id`, order_money) VALUES (2, 150, 200);

INSERT INTO `zstb_orders_goods`(`order_id`,`org_id`,`goods_id`,`goods_name`) VALUES (2, 150, 1, '酸奶');

INSERT INTO `zstb_orders_goods`(`order_id`,`org_id`,`goods_id`,`goods_name`) VALUES (2, 150, 2, '纯奶');

INSERT INTO `zstb_orders`(`order_id`, `org_id`, order_money) VALUES (3, 350, 200);

INSERT INTO `zstb_orders_goods`(`order_id`,`org_id`,`goods_id`,`goods_name`) VALUES (3, 350, 1, '酸奶');

INSERT INTO `zstb_orders_goods`(`order_id`,`org_id`,`goods_id`,`goods_name`) VALUES (3, 350, 2, '纯奶');

接下来我们来进行查询分析:

EXPLAIN PARTITIONS SELECT * FROM `zstb_orders` WHERE org_id = 150;

mysql表分区多表链接查询_MySql分区后创建索引加速单表查询和连表查询

我们对订单表进行查询的时候,发现虽然仅仅扫描‘p2’分区,但是没有使用到主键索引,有点遗憾。

同样,我们也对订单商品表进行查询分析:

EXPLAIN PARTITIONS SELECT * FROM `zstb_orders_goods` WHERE org_id = 150;

mysql表分区多表链接查询_MySql分区后创建索引加速单表查询和连表查询

结果还是只扫描'p2'分区,并没有使用到主键索引。

我们再分析连表查询试试:

EXPLAIN PARTITIONS SELECT * FROM `zstb_orders` AS o JOIN `zstb_orders_goods` AS g ON o.order_id = g.order_id WHERE o.org_id = 150;

mysql表分区多表链接查询_MySql分区后创建索引加速单表查询和连表查询

对主表‘zstb_orders’的查询虽然只扫描‘p2’分区,但是没有使用主键索引。

对连表‘zstb_orders_goods’的查询是扫描全表,但是使用了主键索引,为什么没有扫描具体的分区表呢?

EXPLAIN PARTITIONS SELECT * FROM `zstb_orders` AS o JOIN `zstb_orders_goods` AS g ON o.order_id = g.order_id AND o.org_id = g.org_id WHERE o.org_id = 150;

考虑‘zstb_orders_goods’是通过'org_id'进行分区的,但是连表查询的时候,没有指明对'org_id',我们只需要在关联查询条件

上面增加‘org_id’的关联即可,分析如下:

主表查询没有变化,连表‘zstb_orders_goods’的查询虽然找到了分区表'p2',但是索引又丢失了!

所以,如果我们需要建立分区的同时,还要使用索引的话,得重新创建了。

ALTER TABLE `zstb_orders_goods` ADD INDEX org_id_index(`org_id`);

mysql表分区多表链接查询_MySql分区后创建索引加速单表查询和连表查询

创建完之后,我们先看看单表查询情况:

EXPLAIN PARTITIONS SELECT * FROM `zstb_orders_goods` WHERE org_id = 150;

mysql表分区多表链接查询_MySql分区后创建索引加速单表查询和连表查询

刚才虽然扫描了'p2'分区,但是没有使用索引,这次我们创建索引后,它就用上了,OK!

在分析刚才的连表查询语句:

EXPLAIN PARTITIONS SELECT * FROM `zstb_orders` AS o JOIN `zstb_orders_goods` AS g ON o.order_id = g.order_id AND o.org_id = g.org_id WHERE o.org_id = 150;

mysql表分区多表链接查询_MySql分区后创建索引加速单表查询和连表查询

即扫描了分区表,又使用到了索引!

当然,如果希望主表'zstb_orders'查询的时候也使用索引的话,那么我们也需要对'zstb_orders'创建'org_id'索引即可。

————————————————

版权声明:本文为CSDN博主「咆哮的程序猿」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。

原文链接:https://blog.csdn.net/konkon2012/article/details/96482548