zoukankan      html  css  js  c++  java
  • (六)MySQL三表索引优化

    建表语句

    CREATE TABLE IF NOT EXISTS `phone`(
    `phoneid` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
    `card` INT(10) UNSIGNED NOT NULL,
    PRIMARY KEY(`phoneid`)
    )ENGINE = INNODB;
    
    INSERT INTO phone(card) VALUES(FLOOR(1 + (RAND() * 20)));
    INSERT INTO phone(card) VALUES(FLOOR(1 + (RAND() * 20)));
    INSERT INTO phone(card) VALUES(FLOOR(1 + (RAND() * 20)));
    INSERT INTO phone(card) VALUES(FLOOR(1 + (RAND() * 20)));
    INSERT INTO phone(card) VALUES(FLOOR(1 + (RAND() * 20)));
    INSERT INTO phone(card) VALUES(FLOOR(1 + (RAND() * 20)));
    INSERT INTO phone(card) VALUES(FLOOR(1 + (RAND() * 20)));
    INSERT INTO phone(card) VALUES(FLOOR(1 + (RAND() * 20)));
    INSERT INTO phone(card) VALUES(FLOOR(1 + (RAND() * 20)));
    INSERT INTO phone(card) VALUES(FLOOR(1 + (RAND() * 20)));
    INSERT INTO phone(card) VALUES(FLOOR(1 + (RAND() * 20)));
    INSERT INTO phone(card) VALUES(FLOOR(1 + (RAND() * 20)));
    INSERT INTO phone(card) VALUES(FLOOR(1 + (RAND() * 20)));
    INSERT INTO phone(card) VALUES(FLOOR(1 + (RAND() * 20)));
    INSERT INTO phone(card) VALUES(FLOOR(1 + (RAND() * 20)));
    INSERT INTO phone(card) VALUES(FLOOR(1 + (RAND() * 20)));
    INSERT INTO phone(card) VALUES(FLOOR(1 + (RAND() * 20)));
    INSERT INTO phone(card) VALUES(FLOOR(1 + (RAND() * 20)));
    INSERT INTO phone(card) VALUES(FLOOR(1 + (RAND() * 20)));
    INSERT INTO phone(card) VALUES(FLOOR(1 + (RAND() * 20)));
    

    使用explain解读SQL

    mysql> explain select * from class LEFT JOIN book on class.card=book.card LEFT JOIN phone on book.card = phone.card;
    +----+-------------+-------+------------+-------+---------------+------+---------+-----------------+------+----------+----------------------------------------------------+
    | id | select_type | table | partitions | type  | possible_keys | key  | key_len | ref             | rows | filtered | Extra                                              |
    +----+-------------+-------+------------+-------+---------------+------+---------+-----------------+------+----------+----------------------------------------------------+
    |  1 | SIMPLE      | class | NULL       | index | NULL          | Y    | 4       | NULL            |   24 |   100.00 | Using index                                        |
    |  1 | SIMPLE      | book  | NULL       | ref   | Y             | Y    | 4       | test.class.card |    1 |   100.00 | Using index                                        |
    |  1 | SIMPLE      | phone | NULL       | ALL   | NULL          | NULL | NULL    | NULL            |   20 |   100.00 | Using where; Using join buffer (Block Nested Loop) |
    +----+-------------+-------+------------+-------+---------------+------+---------+-----------------+------+----------+----------------------------------------------------+
    3 rows in set, 1 warning (0.00 sec)
    
    • 可以看到phone表的type为all, Extra中显示使用了连接缓冲区区。

    创建phone表的card索引

    alter table `phone` add index Z(`card`);
    
    • 再用explain查看sql语句
    mysql> explain select * from class LEFT JOIN book on class.card=book.card LEFT JOIN phone on book.card = phone.card;
    +----+-------------+-------+------------+-------+---------------+------+---------+-----------------+------+----------+-------------+
    | id | select_type | table | partitions | type  | possible_keys | key  | key_len | ref             | rows | filtered | Extra       |
    +----+-------------+-------+------------+-------+---------------+------+---------+-----------------+------+----------+-------------+
    |  1 | SIMPLE      | class | NULL       | index | NULL          | Y    | 4       | NULL            |   24 |   100.00 | Using index |
    |  1 | SIMPLE      | book  | NULL       | ref   | Y             | Y    | 4       | test.class.card |    1 |   100.00 | Using index |
    |  1 | SIMPLE      | phone | NULL       | ref   | Z             | Z    | 4       | test.book.card  |    1 |   100.00 | Using index |
    +----+-------------+-------+------------+-------+---------------+------+---------+-----------------+------+----------+-------------+
    

    注意rows: 扫描的行数

    • 其实可以做更好的优化:
    mysql> explain select * from phone LEFT JOIN book on phone.card=book.card LEFT JOIN class on book.card = class.card;
    +----+-------------+-------+------------+-------+---------------+------+---------+-----------------+------+----------+-------------+
    | id | select_type | table | partitions | type  | possible_keys | key  | key_len | ref             | rows | filtered | Extra       |
    +----+-------------+-------+------------+-------+---------------+------+---------+-----------------+------+----------+-------------+
    |  1 | SIMPLE      | phone | NULL       | index | NULL          | Z    | 4       | NULL            |   20 |   100.00 | Using index |
    |  1 | SIMPLE      | book  | NULL       | ref   | Y             | Y    | 4       | test.phone.card |    1 |   100.00 | Using index |
    |  1 | SIMPLE      | class | NULL       | ref   | Y             | Y    | 4       | test.book.card  |    1 |   100.00 | Using index |
    +----+-------------+-------+------------+-------+---------------+------+---------+-----------------+------+----------+-------------+
    3 rows in set, 1 warning (0.00 sec)
    

    思想: 用小表驱动大表, 能更好地减少行扫描次数。

    • 结论:
      • 索引最好设置在需要经常查询的字段中
      • 尽可能减少Join语句中的NestedLoop(嵌套循环)的循环总数(优先优化NestedLoop内层循环)
      • 永远用小结果集驱动大的结果集

    转载:https://www.cnblogs.com/ronnieyuan/p/12162240.html

  • 相关阅读:
    WebApi接口返回值不困惑:返回值类型详解
    Autofac 依赖注入框架 使用
    ASP.NET Core:使用Dapper和SwaggerUI来丰富你的系统框架
    ASP .Net Core 使用 Dapper 轻型ORM框架
    基于AspNet Core2.0 开发框架,包含简单的个人博客Demo
    Asp.Net MVC及Web API框架配置会碰到的几个问题及解决方案 (精髓)
    精简版自定义 jquery
    vs code 前端如何以服务器模式打开 [安装服务器] server insteall
    RestSharp用法小结
    翻译:WebApi 认证--用户认证Oauth解析
  • 原文地址:https://www.cnblogs.com/everyingo/p/13895423.html
Copyright © 2011-2022 走看看