索引优化

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
RDS MySQL Serverless 高可用系列,价值2615元额度,1个月
简介: 索引优化

选择驱动表

默认选择方式(非驱动表):

按照on的条件列,是否有索引,索引的类型选择。

1. 在on条件中,优化器优先选择有索引的列为非驱动表。

2. 如果两个列都有索引,优化器会按照执行的代价去选择驱动表和非驱动表。

for each row in course matching range {
  block 
    for each row in teacher {
      course.tno = tracher.tno ,send to client
    }
}

关于驱动表选择的优化思路:

理论支撑:
mysql> desc   select * from city left join country on city.countrycode=country.code ;
+----+-------------+---------+------------+--------+---------------+---------+---------+------------------------+------+----------+-------+
| id | select_type | table   | partitions | type   | possible_keys | key     | key_len | ref                    | rows | filtered | Extra |
+----+-------------+---------+------------+--------+---------------+---------+---------+------------------------+------+----------+-------+
|  1 | SIMPLE      | city    | NULL       | ALL    | NULL          | NULL    | NULL    | NULL                   | 4188 |   100.00 | NULL  |
|  1 | SIMPLE      | country | NULL       | eq_ref | PRIMARY       | PRIMARY | 3       | world.city.CountryCode |    1 |   100.00 | NULL  |
+----+-------------+---------+------------+--------+---------------+---------+---------+------------------------+------+----------+-------+
2 rows in set, 1 warning (0.00 sec)
查询语句执行代价:
mysql> desc   format=json select * from city join country on city.countrycode=country.code ;
···
{
  "query_block": {
    "select_id": 1,
    "cost_info": {
      "query_cost": "5231.03"
    },
    "nested_loop": [
      {
        "table": {
          "table_name": "country",
          "access_type": "ALL",
          "possible_keys": [
            "PRIMARY"
          ],
          "rows_examined_per_scan": 239,
          "rows_produced_per_join": 239,
          "filtered": "100.00",
          "cost_info": {
            "read_cost": "6.00",
            "eval_cost": "47.80",
            "prefix_cost": "53.80",
            "data_read_per_join": "61K"
          },
          "used_columns": [
            "Code",
            "Name",
            "Continent",
            "Region",
            "SurfaceArea",
            "IndepYear",
            "Population",
            "LifeExpectancy",
            "GNP",
            "GNPOld",
            "LocalName",
            "GovernmentForm",
            "HeadOfState",
            "Capital",
            "Code2"
          ]
        }
      },
      {
        "table": {
          "table_name": "city",
          "access_type": "ref",
          "possible_keys": [
            "CountryCode"
          ],
          "key": "CountryCode",
          "used_key_parts": [
            "CountryCode"
          ],
          "key_length": "3",
          "ref": [
            "world.country.Code"
          ],
          "rows_examined_per_scan": 18,
          "rows_produced_per_join": 4314,
          "filtered": "100.00",
          "cost_info": {
            "read_cost": "4314.36",
            "eval_cost": "862.87",
            "prefix_cost": "5231.03",
            "data_read_per_join": "303K"
          },
          "used_columns": [
            "ID",
            "Name",
            "CountryCode",
            "District",
            "Population"
          ]
        }
      }
    ]
  }
} |
···

实践检验:

mysqlslap --defaults-file=/etc/my.cnf --concurrency=100 --iterations=1 --create-schema='world' --query="select * from city left join country on city.countrycode=country.code ;" engine=innodb --number-of-queries=2000 -uroot -p123456 -verbose
mysqlslap --defaults-file=/etc/my.cnf --concurrency=100 --iterations=1 --create-schema='world' --query="select * from city  join country on city.countrycode=country.code ;" engine=innodb --number-of-queries=2000 -uroot -p123456 -verbose

注:可以通过 left join 强制驱动表。

总结:多表连接优化

驱动表选择

A  join  B  on  A.x=b.y

让优化器自己决定

在on条件中,优化器优先选择有索引的列为非驱动表。
如果两个列都有索引,优化器会按照执行的代价去选择驱动表和非驱动表。

自主选择

left join强制驱动表

关于驱动表选择的优化思路

理论支撑:
mysql> desc   select * from city join country on city.countrycode=country.code ;
mysql> desc   select * from city left join country on city.countrycode=country.code ;
查询语句执行代价:
mysql> desc   format=json select * from city join country on city.countrycode=country.code ;
mysql> desc   format=json select * from city left join country on city.countrycode=country.code ;

实践检验:

mysqlslap --defaults-file=/etc/my.cnf --concurrency=100 --iterations=1 --create-schema='world' --query="select * from city left join country on city.countrycode=country.code ;" engine=innodb --number-of-queries=2000 -uroot -p123456 -verbose
mysqlslap --defaults-file=/etc/my.cnf --concurrency=100 --iterations=1 --create-schema='world' --query="select * from city  join country on city.countrycode=country.code ;" engine=innodb --number-of-queries=2000 -uroot -p123456 -verbose

驱动情景

情景一:触发SNL的情况

非驱动表,关联条件 如果没有任何索引的话,只能默认使用SNL算法
代价较高,建议做合理优化。
例如:将非驱动表关联条件建立索引。
      (1)主键或唯一键,会自动使用eq_ref算法进行执行查询。
      (2)辅助索引,默认会采用BNL。如果开启BKA,会走BKA。

情景二:触发BNL的情况

非驱动表,连接条件如果有普通索引。会默认会用BNL

情景三:触发BKA的情况

非驱动表,连接条件如果有普通索引。
默认是关闭的,启动方式:
mysql> set global optimizer_switch='mrr=on,mrr_cost_based=off';
mysql> set global optimizer_switch='batched_key_access=on';

选择 BNL和BKA算法的判断思路

理论支撑:
mysql> desc   select * from city join country on city.countrycode=country.code ;
mysql> desc   select * from city left join country on city.countrycode=country.code ;
查询语句执行代价:
mysql> desc   format=json select * from city join country on city.countrycode=country.code ;
mysql> desc   format=json select * from city left join country on city.countrycode=country.code ;

实践检验:

[root@db01 ~]# mysqlslap --defaults-file=/etc/my.cnf --concurrency=100 --iterations=1 --create-schema='world' --query="select * from city left join country on city.countrycode=country.code ;" engine=innodb --number-of-queries=2000 -uroot -p123 -verbose
[root@db01 ~]# mysqlslap --defaults-file=/etc/my.cnf --concurrency=100 --iterations=1 --create-schema='world' --query="select * from city  join country on city.countrycode=country.code ;" engine=innodb --number-of-queries=2000 -uroot -p123 -verbose
相关实践学习
基于CentOS快速搭建LAMP环境
本教程介绍如何搭建LAMP环境,其中LAMP分别代表Linux、Apache、MySQL和PHP。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
6天前
|
关系型数据库 MySQL 数据库
MySQL索引和查询优化
MySQL索引和查询优化
40 1
|
8月前
|
索引
索引优化
索引优化
344 0
|
6天前
|
SQL 存储 关系型数据库
MySQL索引(二)索引优化方案有哪些
MySQL索引(二)索引优化方案有哪些
62 0
|
存储 SQL 关系型数据库
Mysql优化之索引(二)
Mysql优化之索引(二)
Mysql优化之索引(二)
|
存储 SQL 缓存
MySQL索引与查询优化
MySQL由于其性能高、成本低、可靠性好,已经成为最流行的开源数据库之一。提升查询速度的技术有很多,其中最重要的就是索引。当你发现自己的查询速度慢的时候,最快解决问题的方法就是使用索引。索引的使用是影响查询速度的重要因素。在使用索引之前其他的优化查询的动作纯粹是浪费时间,只有合理地使用索引之后,才有必要考虑其他优化方式。
74 0
MySQL索引与查询优化
|
SQL 前端开发 关系型数据库
索引优化|学习笔记
快速学习索引优化
91 0
索引优化|学习笔记
|
SQL 关系型数据库 MySQL
索引优化7|学习笔记
快速学习索引优化7
64 0
索引优化7|学习笔记
|
存储 SQL 关系型数据库
索引优化8|学习笔记
快速学习索引优化8
117 0
索引优化8|学习笔记
|
关系型数据库 MySQL 开发者
索引优化10|学习笔记
快速学习索引优化10
49 0
|
关系型数据库 MySQL 开发者
索引优化6|学习笔记
快速学习索引优化6
49 0
索引优化6|学习笔记