• MySQL索引的维护


    1.找出未使用的索引

    结合sys schema查询

    mysql> select * from sys.schema_unused_indexes;
    +---------------+-----------------+-------------+
    | object_schema | object_name     | index_name |
    +---------------+-----------------+-------------+
    | world         | City           | CountryCode |
    | world         | CountryLanguage | CountryCode |
    +---------------+-----------------+-------------+
    2 rows in set (0.01 sec)

    视图schema_unused_indexes是基于表performance_schema.table_io_waits_summary_by_index_usage。需要开启performance_schema、events_waits_current consumer和wait/io/table/sql/handler instrument。

    逐渐会被忽略。

    可以执行以下命令开启:

    update performance_schema.setup_consumers set enabled = 'yes' where name = 'events_waits_current';
    update performance_schema.setup_instruments set enabled = 'yes' where name = 'wait/io/table/sql/handler';

    发现有未使用的索引之后,删除即可。

    开启对应consumer和instrument之后,一定要运行一段时间,生成的数据才可靠。

    比如,如果有个月度任务,那至少要运行一个月,数据才会可靠。

     

    2.找出重复的索引

    (1)使用pt-duplicate-key-chekcer

    [root@e51d333b1fbe mysql-sys]# pt-duplicate-key-checker
    # ########################################################################
    # world.CountryLanguage
    # ########################################################################

    # CountryCode is a left-prefix of PRIMARY
    # Key definitions:
    #   KEY `CountryCode` (`CountryCode`),
    #   PRIMARY KEY (`CountryCode`,`Language`),
    # Column types:
    #     `countrycode` char(3) not null default ''
    #     `language` char(30) not null default ''
    # To remove this duplicate index, execute:
    ALTER TABLE `world`.`CountryLanguage` DROP INDEX `CountryCode`;

    # ########################################################################
    # Summary of indexes
    # ########################################################################

    # Size Duplicate Indexes   2952
    # Total Duplicate Indexes 1
    # Total Indexes           37

    (2)使用视图sys.schema_redundant_indexes

    sys.schema_redundant_indexes是基于表information_schema.statistics

    mysql> select * from schema_redundant_indexesG
    *************************** 1. row ***************************
                table_schema: world
                  table_name: CountryLanguage
        redundant_index_name: CountryCode
      redundant_index_columns: CountryCode
    redundant_index_non_unique: 1
          dominant_index_name: PRIMARY
      dominant_index_columns: CountryCode,Language
    dominant_index_non_unique: 0
              subpart_exists: 0
              sql_drop_index: ALTER TABLE `world`.`CountryLanguage` DROP INDEX `CountryCode`
    1 row in set (0.00 sec)

     

    3.可能缺失的索引

    视图sys.statements_with_full_table_scans

    mysql> select * from world.CountryLanguage where isOfficial = 'F';
    55a208785be7a5beca68b147c58fe634 -
    746 rows in set (0.00 sec)

    mysql> select * from statements_with_full_table_scansG
    *************************** 1. row ***************************
                      query: SELECT * FROM `world` . `Count ... guage` WHERE `isOfficial` = ?
                        db: world
                exec_count: 1
              total_latency: 739.87 us
        no_index_used_count: 1
    no_good_index_used_count: 0
          no_index_used_pct: 100
                  rows_sent: 746
              rows_examined: 984
              rows_sent_avg: 746
          rows_examined_avg: 984
                first_seen: 2016-09-05 19:51:31
                  last_seen: 2016-09-05 19:51:31
                    digest: aa637cf0867616c591251fac39e23261
    1 row in set (0.01 sec)

    找出全表扫描的语句之后,可以使用explain看下具体的执行计划:

    mysql> explain select * from world.CountryLanguage where isOfficial = 'F'G
    *************************** 1. row ***************************
              id: 1
    select_type: SIMPLE
          table: CountryLanguage
            type: ALL
    possible_keys: NULL
            key: NULL
        key_len: NULL
            ref: NULL
            rows: 984
          Extra: Using where

    可以分析一下,看看是否需要增加合适的索引。

     

    4.多列索引的顺序

    多列索引的列的顺序很重要。

    假设有一张表

    mysql> show create table CountryLanguageG
    *************************** 1. row ***************************
          Table: CountryLanguage
    Create Table: CREATE TABLE `CountryLanguage` (
    `CountryCode` char(3) NOT NULL DEFAULT '',
    `Language` char(30) NOT NULL DEFAULT '',
    `IsOfficial` enum('T','F') NOT NULL DEFAULT 'F',
    `Percentage` float(4,1) NOT NULL DEFAULT '0.0',
    PRIMARY KEY (`CountryCode`,`Language`),
    KEY `CountryCode` (`CountryCode`),
    CONSTRAINT `countryLanguage_ibfk_1` FOREIGN KEY (`CountryCode`) REFERENCES `Country` (`Code`)
    ) ENGINE=InnoDB DEFAULT CHARSET=latin1

    下面的查询就无法使用到索引:

    mysql> explain select * from CountryLanguage where Language = 'English'\G
    *************************** 1. row ***************************
              id: 1
    select_type: SIMPLE
          table: CountryLanguage
            type: ALL
    possible_keys: NULL
            key: NULL
        key_len: NULL
            ref: NULL
            rows: 984
          Extra: Using where

    如果在查询条件中增加一个条件:CountryCode

    就可以使用到索引了。

    mysql> explain select * from CountryLanguage where Language = 'English' and CountryCode = 'CAN'G
    *************************** 1. row ***************************
              id: 1
    select_type: SIMPLE
          table: CountryLanguage
            type: const
    possible_keys: PRIMARY,CountryCode
            key: PRIMARY
        key_len: 33
            ref: const,const
            rows: 1
          Extra: NULL

    这时就需要分外考虑列的选择性了,哪个放在前面更好。

    在这个例子中,"language"的选择性比"countrycode"好:

    mysql> select count(distinct CountryCode)/count(*), count(distinct Language)/count(*) from CountryLanguage;
    +--------------------------------------+-----------------------------------+
    | count(distinct CountryCode)/count(*) | count(distinct Language)/count(*) |
    +--------------------------------------+-----------------------------------+
    |                               0.2368 |                           0.4644 |
    +--------------------------------------+-----------------------------------+

    在这个例子中,如果我们创建多列索引,推荐的顺序是(language,countrycode)

     

    在没有排序或分组的时候,将选择性最好的放在前面。

    表没有均匀分布的特殊情况怎么办?当单个值出现的次数比所有其他值多时?在这种情况下,任何索引都不够好。注意不要假设平均情况下的性能代表特殊情况下的性能。特殊情况可能会破坏整个应用程序的性能。

    以上测试用例的软件版本是:

    mysql> select * from sys.version;
    +-------------+-----------------+
    | sys_version | mysql_version   |
    +-------------+-----------------+
    | 1.5.1       | 5.6.31-77.0-log |
    +-------------+-----------------+

     

     

     

     

     

     

  • 相关阅读:
    VSCode搭建golang环境
    Jmeter之连接数据库
    Jmeter之『如果(If)控制器』
    mysql时间SQL
    正则表达式查找“不包含XXX字符串”
    Jmeter5.3源码编译
    Log4j源码分析
    12 个 JS 技巧
    高效学习很重要
    IntelliJ IDEA自动导入包去除星号(import xxx.*)
  • 原文地址:https://www.cnblogs.com/abclife/p/15973768.html
Copyright © 2020-2023  润新知