Preface
 
    There're many ways relevent with performance tuning.For example,using indexes properly is important in doing that.At the very beginning of releasing a project,we're probably supposed to create many different indexes(especially union index) to increase the efficiency of queries on target tables even if some of them are seldom or never used at all.We are sure about that it is not the more the better of indexes on a table.Indexes will occupy more disk space and will cost a lot in maintaining.Alternatively,we should reduce the indexes which are not usually used by freqeuntly cheking them.Therefore,I'll introduce a tool which can help us in the aspect.
 
Introduce
 
    pt-index-usage(as what it is called) is a tool of Percona-Toolkit can provide a way to analyze your SQL statments in slow log(which means they're probably executed with bad performance).Afterward,you can know details about whether there're indexes not used properly and estimate whether to drop them in some time later.
 
Procedure
 
Usage
 pt-index-usage [OPTIONS] [FILES]

Main parameter

 --save-results-database -- Save output results into the specific tables of database.
--create-save-results-database -- Create a database with necessary tables if set "--save-results-database" but not exist.
--empty-save-results-tables -- Drop and recreate all the tables which are specified by "--save-results-database".
--create-views -- Create views for tables in database which is specified by "--save-results-database".
--no-report -- Don't generate a report but put results into tables for later analysis."--save-results-database" is indispensable when you set this option.
--report-format -- The only format is "drop_unused_indexes" now.
--drop -- Specify the type of index which you want to drop(Default value is non-unique).
Examples
 
Create test environment.
 (root@localhost mysql3306.sock)[zlm]::>create table if not exists test_index_usage(
-> id int unsigned auto_increment not null,
-> order_id int unsigned not null default ,
-> name varchar() not null default '',
-> gender enum('male','female') not null,
-> primary key(id)
-> ) auto_increment= engine=innodb charset=utf8mb4;
Query OK, rows affected (0.04 sec) (root@localhost mysql3306.sock)[zlm]::>delimiter $$
(root@localhost mysql3306.sock)[zlm]::>create procedure pro_index_usage (in n1 int,in s1 varchar(),in s2 varchar())
-> begin
-> declare i int unsigned default ;
-> start transaction;
-> while i < n1 do
-> insert into test_index_usage(order_id,gender,name) values(i,s1,s2);
-> set i=i+;
-> end while;
-> commit;
-> end;
-> $$
Query OK, rows affected (0.00 sec) (root@localhost mysql3306.sock)[zlm]::>delimiter ;
(root@localhost mysql3306.sock)[zlm]::>call pro_index_usage(,'male','zlm');
Query OK, rows affected (5.59 sec) (root@localhost mysql3306.sock)[zlm]::>call pro_index_usage(,'female','aaron8219');
Query OK, rows affected (5.38 sec) (root@localhost mysql3306.sock)[zlm]::>select count(*) from test_index_usage;
+----------+
| count(*) |
+----------+
| |
+----------+
row in set (0.05 sec) (root@localhost mysql3306.sock)[zlm]::>select * from test_index_usage limit ;
+----+----------+------+--------+
| id | order_id | name | gender |
+----+----------+------+--------+
| | | zlm | male |
| | | zlm | male |
| | | zlm | male |
| | | zlm | male |
| | | zlm | male |
+----+----------+------+--------+
rows in set (0.00 sec) (root@localhost mysql3306.sock)[zlm]::>alter table test_index_usage add key idx_key1 (order_id,gender);
Query OK, rows affected (0.64 sec)
Records: Duplicates: Warnings: (root@localhost mysql3306.sock)[zlm]::>alter table test_index_usage add key idx_key2 (order_id,gender,name);
Query OK, rows affected (0.94 sec)
Records: Duplicates: Warnings: (root@localhost mysql3306.sock)[zlm]::>show keys from test_index_usage;
+------------------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+------------------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| test_index_usage | | PRIMARY | | id | A | | NULL | NULL | | BTREE | | |
| test_index_usage | | idx_key1 | | order_id | A | | NULL | NULL | | BTREE | | |
| test_index_usage | | idx_key1 | | gender | A | | NULL | NULL | | BTREE | | |
| test_index_usage | | idx_key2 | | order_id | A | | NULL | NULL | | BTREE | | |
| test_index_usage | | idx_key2 | | gender | A | | NULL | NULL | | BTREE | | |
| test_index_usage | | idx_key2 | | name | A | | NULL | NULL | | BTREE | | |
+------------------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
rows in set (0.00 sec)

Make sure "slow_query_on" has been set "on" and reduce the "long_query_time" into "0.01".

 (root@localhost mysql3306.sock)[zlm]::>show global variables like '%slow_query_log%';
+---------------------+----------+
| Variable_name | Value |
+---------------------+----------+
| slow_query_log | ON |
| slow_query_log_file | slow.log |
+---------------------+----------+
rows in set (0.00 sec) (root@localhost mysql3306.sock)[zlm]::>show global variables like '%long_query_time%';
+-----------------+----------+
| Variable_name | Value |
+-----------------+----------+
| long_query_time | 1.000000 |
+-----------------+----------+
row in set (0.00 sec) (root@localhost mysql3306.sock)[zlm]::>set global long_query_time=0.01;
Query OK, rows affected (0.00 sec) (root@localhost mysql3306.sock)[zlm]::>show global variables like '%long_query_time%';
+-----------------+----------+
| Variable_name | Value |
+-----------------+----------+
| long_query_time | 0.010000 |
+-----------------+----------+
row in set (0.01 sec)

Execute a SQL statement.

 (root@localhost mysql3306.sock)[zlm]::>select * from test_index_usage where order_id>= and name='aaron8219';
-- Omitted.
| | | aaron8219 | female |
| | | aaron8219 | female |
| | | aaron8219 | female |
| | | aaron8219 | female |
| | | aaron8219 | female |
| | | aaron8219 | female |
| | | aaron8219 | female |
| | | aaron8219 | female |
| | | aaron8219 | female |
| | | aaron8219 | female |
| | | aaron8219 | female |
+--------+----------+-----------+--------+
rows in set (0.16 sec)

Check the execute plan.

 (root@localhost mysql3306.sock)[zlm]::>explain select * from test_index_usage where order_id>= and name='aaron8219';
+----+-------------+------------------+------------+-------+-------------------+----------+---------+------+-------+----------+--------------------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+------------------+------------+-------+-------------------+----------+---------+------+-------+----------+--------------------------+
| | SIMPLE | test_index_usage | NULL | range | idx_key1,idx_key2 | idx_key2 | | NULL | | 10.00 | Using where; Using index |
+----+-------------+------------------+------------+-------+-------------------+----------+---------+------+-------+----------+--------------------------+
row in set, warning (0.00 sec) (root@localhost mysql3306.sock)[zlm]::>explain format=json select * from test_index_usage where order_id>= and name='aaron8219'\G
*************************** . row ***************************
EXPLAIN: {
"query_block": {
"select_id": ,
"cost_info": {
"query_cost": "40540.88"
},
"table": {
"table_name": "test_index_usage",
"access_type": "range",
"possible_keys": [
"idx_key1",
"idx_key2"
],
"key": "idx_key2",
"used_key_parts": [
"order_id"
],
"key_length": "",
"rows_examined_per_scan": ,
"rows_produced_per_join": ,
"filtered": "10.00",
"using_index": true,
"cost_info": {
"read_cost": "38544.88",
"eval_cost": "1996.00",
"prefix_cost": "40540.88",
"data_read_per_join": "545K"
},
"used_columns": [
"id",
"order_id",
"name",
"gender"
],
"attached_condition": "((`zlm`.`test_index_usage`.`order_id` >= 1) and (`zlm`.`test_index_usage`.`name` = 'aaron8219'))"
}
}
}
row in set, warning (0.00 sec)

Check slow log.

 [root@zlm2 :: /data/mysql/mysql3306/data]
#cat slow.log # Time: --25T08::.974728Z
# User@Host: root[root] @ localhost [] Id:
# Query_time: 0.161343 Lock_time: 0.000087 Rows_sent: Rows_examined:
SET timestamp=;
select * from test_index_usage where order_id>= and name='aaron8219';
Execute pt-index-usage(create database and tables & views).
 [root@zlm2 :: /data/mysql/mysql3306/data]
#pt-index-usage -h192.168.1. -P3306 -urepl -prepl4slave -Dzlm --create-views --no-report --create-save-results-database --save-results-database h=192.168.1.102,P=,u=repl,p=repl4slave,D=index_usage /data/mysql/mysql3306/data/slow.log [root@zlm2 :: /data/mysql/mysql3306/data]
#
Check the tables & views in database "index_usage" on remote node zlm3.
 (root@localhost mysql3306.sock)[(none)]::>show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| index_usage | -- This is the newly create database which contains tables created by pt-index-usage.
| mysql |
| performance_schema |
| sys |
| zlm |
+--------------------+
rows in set (0.00 sec) (root@localhost mysql3306.sock)[(none)]::>use index_usage;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A Database changed
(root@localhost mysql3306.sock)[index_usage]::>show tables;
+---------------------------------+
| Tables_in_index_usage |
+---------------------------------+
| index_alternatives |
| index_usage |
| indexes |
| queries |
| tables |
| view_index_alternates |
| view_index_has_alternates |
| view_index_usage |
| view_query_uses_several_indexes |
| view_required_indexes |
| view_unused_index_alternates |
+---------------------------------+
rows in set (0.00 sec) (root@localhost mysql3306.sock)[index_usage]::>select * from index_alternatives;
+---------------------+-----+------------------+----------+----------+-----+
| query_id | db | tbl | idx | alt_idx | cnt |
+---------------------+-----+------------------+----------+----------+-----+
| | zlm | test_index_usage | idx_key2 | idx_key1 | |
+---------------------+-----+------------------+----------+----------+-----+
row in set (0.00 sec) (root@localhost mysql3306.sock)[index_usage]::>select * from index_usage;
+---------------------+-----+------------------+----------+-----+
| query_id | db | tbl | idx | cnt |
+---------------------+-----+------------------+----------+-----+
| | zlm | test_index_usage | idx_key2 | |
+---------------------+-----+------------------+----------+-----+
row in set (0.00 sec) (root@localhost mysql3306.sock)[index_usage]::>select * from indexes;
+-------+---------------------------+-----------+-----+
| db | tbl | idx | cnt |
+-------+---------------------------+-----------+-----+
| mysql | columns_priv | PRIMARY | |
| mysql | db | PRIMARY | |
| mysql | db | User | |
| mysql | engine_cost | PRIMARY | |
| mysql | event | PRIMARY | |
| mysql | func | PRIMARY | |
| mysql | help_category | name | |
| mysql | help_category | PRIMARY | |
| mysql | help_keyword | name | |
| mysql | help_keyword | PRIMARY | |
| mysql | help_relation | PRIMARY | |
| mysql | help_topic | name | |
| mysql | help_topic | PRIMARY | |
| mysql | ndb_binlog_index | PRIMARY | |
| mysql | plugin | PRIMARY | |
| mysql | proc | PRIMARY | |
| mysql | procs_priv | Grantor | |
| mysql | procs_priv | PRIMARY | |
| mysql | proxies_priv | Grantor | |
| mysql | proxies_priv | PRIMARY | |
| mysql | servers | PRIMARY | |
| mysql | server_cost | PRIMARY | |
| mysql | tables_priv | Grantor | |
| mysql | tables_priv | PRIMARY | |
| mysql | time_zone | PRIMARY | |
| mysql | time_zone_leap_second | PRIMARY | |
| mysql | time_zone_name | PRIMARY | |
| mysql | time_zone_transition | PRIMARY | |
| mysql | time_zone_transition_type | PRIMARY | |
| mysql | user | PRIMARY | |
| sys | sys_config | PRIMARY | |
| zlm | checksums | PRIMARY | |
| zlm | checksums | ts_db_tbl | |
| zlm | indexes | PRIMARY | |
| zlm | index_alternatives | db | |
| zlm | index_alternatives | db_2 | |
| zlm | index_alternatives | query_id | |
| zlm | index_usage | query_id | |
| zlm | queries | PRIMARY | |
| zlm | tables | PRIMARY | |
| zlm | test_ddl | PRIMARY | |
| zlm | test_index_usage | idx_key1 | |
| zlm | test_index_usage | idx_key2 | |
| zlm | test_index_usage | PRIMARY | |
| zlm | test_innodb | PRIMARY | |
| zlm | test_myisam | PRIMARY | |
+-------+---------------------------+-----------+-----+
rows in set (0.00 sec) (root@localhost mysql3306.sock)[index_usage]::>select * from queries\G
*************************** . row ***************************
query_id:
fingerprint: create table if not exists tables ( db varchar(?) not ?, tbl varchar(?) not ?, cnt bigint unsigned not ? default ?, primary key (db, tbl) )
sample: CREATE TABLE IF NOT EXISTS tables (
db VARCHAR() NOT NULL,
tbl VARCHAR() NOT NULL,
cnt BIGINT UNSIGNED NOT NULL DEFAULT ,
PRIMARY KEY (db, tbl)
)
*************************** . row ***************************
query_id:
fingerprint: select * from test_index_usage where order_id>=? and name=?
sample: select * from test_index_usage where order_id>= and name='aaron8219'
*************************** . row ***************************
query_id:
fingerprint: create table if not exists indexes ( db varchar(?) not ?, tbl varchar(?) not ?, idx varchar(?) not ?, cnt bigint unsigned not ? default ?, primary key (db, tbl, idx) )
sample: CREATE TABLE IF NOT EXISTS indexes (
db VARCHAR() NOT NULL,
tbl VARCHAR() NOT NULL,
idx VARCHAR() NOT NULL,
cnt BIGINT UNSIGNED NOT NULL DEFAULT ,
PRIMARY KEY (db, tbl, idx)
)
*************************** . row ***************************
query_id:
fingerprint: create table if not exists queries ( query_id bigint unsigned not ?, fingerprint text not ?, sample text not ?, primary key (query_id) )
sample: CREATE TABLE IF NOT EXISTS queries (
query_id BIGINT UNSIGNED NOT NULL,
fingerprint TEXT NOT NULL,
sample TEXT NOT NULL,
PRIMARY KEY (query_id)
)
*************************** . row ***************************
query_id:
fingerprint: create table if not exists index_alternatives ( query_id bigint unsigned not ?, db varchar(?) not ?, tbl varchar(?) not ?, idx varchar(?) not ?, alt_idx varchar(?) not ?, cnt bigint unsigned not ? default ?, unique index (query_id, db, tbl, idx, alt_idx), index (db, tbl, idx), index (db, tbl, alt_idx) )
sample: CREATE TABLE IF NOT EXISTS index_alternatives (
query_id BIGINT UNSIGNED NOT NULL, -- This query used
db VARCHAR() NOT NULL, -- this index, but...
tbl VARCHAR() NOT NULL, --
idx VARCHAR() NOT NULL, --
alt_idx VARCHAR() NOT NULL, -- was an alternative
cnt BIGINT UNSIGNED NOT NULL DEFAULT ,
UNIQUE INDEX (query_id, db, tbl, idx, alt_idx),
INDEX (db, tbl, idx),
INDEX (db, tbl, alt_idx)
)
rows in set (0.00 sec) (root@localhost mysql3306.sock)[index_usage]::>select * from tables;
+-------+---------------------------+-----+
| db | tbl | cnt |
+-------+---------------------------+-----+
| mysql | columns_priv | |
| mysql | db | |
| mysql | engine_cost | |
| mysql | event | |
| mysql | func | |
| mysql | help_category | |
| mysql | help_keyword | |
| mysql | help_relation | |
| mysql | help_topic | |
| mysql | ndb_binlog_index | |
| mysql | plugin | |
| mysql | proc | |
| mysql | procs_priv | |
| mysql | proxies_priv | |
| mysql | servers | |
| mysql | server_cost | |
| mysql | tables_priv | |
| mysql | time_zone | |
| mysql | time_zone_leap_second | |
| mysql | time_zone_name | |
| mysql | time_zone_transition | |
| mysql | time_zone_transition_type | |
| mysql | user | |
| sys | sys_config | |
| zlm | checksums | |
| zlm | indexes | |
| zlm | index_alternatives | |
| zlm | index_usage | |
| zlm | queries | |
| zlm | tables | |
| zlm | test_ddl | |
| zlm | test_ddl_no_pk | |
| zlm | test_index_usage | |
| zlm | test_innodb | |
| zlm | test_myisam | |
+-------+---------------------------+-----+
rows in set (0.00 sec)
Execute pt-index-usage(output on screen derectly).
 [root@zlm2 :: /data/mysql/mysql3306/data]
#pt-index-usage -h192.168.1. -P3306 -urepl -prepl4slave -Dzlm /data/mysql/mysql3306/data/slow.log ALTER TABLE `zlm`.`test_index_usage` DROP KEY `idx_key1`; -- type:non-unique [root@zlm2 :: /data/mysql/mysql3306/data]
#
summary
  • pt-index-usage provides merely analysis on slow log at the moment.
  • Usually We'll analyze SQL statements in slow log,and then put them into tables of database on remote server(which maybe not slave).
  • There will be a series of insert operations when using pt-index-usage(while not setting "--no-report").Thus,it really will I ncreast the load of product server.
  • On the other hand,It's possible to be misled when we get a probable bad execute plan which bypasses the useful indexes.
 

Percona-Tookit工具包之pt-index-usage的更多相关文章

  1. Percona Toolkit mysql辅助利器

    1 PT介绍 Percona Toolkit简称pt工具—PT-Tools,是Percona公司开发用于管理MySQL的工具,功能包括检查主从复制的数据一致性.检查重复索引.定位IO占用高的表文件.在 ...

  2. Oracle composite index column ordering

    Question:  I have a SQL with multiple columns in my where clause.  I know that Oracle can only choos ...

  3. Oracle alter index rebuild 与 ORA-08104 说明

    在ITPUB 论坛上看到的一个帖子,很不错.根据论坛的帖子重做整理了一下. 原文链接如下: alter index rebuild online引发的血案 http://www.itpub.net/t ...

  4. Percona XtraBackup使用说明(转)

    Percona XtraBackup使用说明 转载出自: https://blog.csdn.net/wfs1994/article/details/80396604 XtraBackup介绍 Per ...

  5. Index Skip Scan in Oracle in 11g

    http://viralpatel.net/blogs/oracle-index-skip-scan/ in 11g the same sql use index skip scan but in 1 ...

  6. oracle alter index rebuild offline与online

    oracle index build online与offline测试环境为oracle 11.2.0.4 --sql test SQL> conn test/test )); begin .. ...

  7. pt-online-schema-change的原理解析与应用说明

          PERCONA提供了若干管理维护MySQL的小工具,集成在 PERCONA Toolkit工具中,有慢查询分析.主从差异对比.主从差异修复及在线表结构修改等工具,个人觉得挺好用的.本文简单 ...

  8. Linux后台开发工具箱

    https://files-cdn.cnblogs.com/files/aquester/Linux后台开发工具箱.pdf 目录 目录 1 1. 前言 3 2. 脚本类工具 3 2.1. sed命令- ...

  9. Mysql: pt-table-checksum 和 pt-table-sync 检查主从一致性,实验过程

    一.安装 percona 包 1.安装仓库的包 https://www.percona.com/doc/percona-repo-config/yum-repo.html sudo yum insta ...

  10. Linux后台开发工具箱-葵花宝典

    Linux后台开发工具箱-葵花宝典 一见 2016/11/4 目录 目录 1 1. 前言 4 2. 脚本类工具 4 2.1. 双引号和单引号 4 2.2. 取脚本完整文件路径 5 2.3. 环境变量和 ...

随机推荐

  1. SSO单点登录三种情况的实现方式详解(转)

    https://blog.csdn.net/ainuser/article/details/65631713

  2. Java的输入/输出操作

    Java的输入\输出机制 计算机的基本功能就是通过输入输出设备与外部其他设备尽心数据的交互,从其他设备读入数据叫做输入操作,将计算机内的数据写入到其他设备叫做输出操作.可以向计算机发送数据.又可以接受 ...

  3. iPython与notebook的基本用法

    1 Ipython 安装 pip install ipython 2 Notebooke 基本用法 启动ipython使用ipython 启动notebook 使用 ipython notebook ...

  4. 基于alpine定制常用命令镜像

    FROM alpine RUN apk update RUN apk add curl coreutils 像busybox.alpine镜像date命令都不是完整版的,不能执行加减的操作(date ...

  5. CRM订单状态的Open, In process和Completed这些条目是从哪里来的

    Service Order的状态字段里的这些字段从哪里带出来的?我们可能会想当然的认为是从后台配的Status profile里带出来的.事实并非如此. 这个transaction type根本没有分 ...

  6. 前端:Bootstrap框架

    一,bootstrap介绍 Bootstrap是Twitter开源的基于HTML.CSS.JavaScript的前端框架. 它是为实现快速开发Web应用程序而设计的一套前端工具包. 它支持响应式布局, ...

  7. 【LOJ2461】「2018 集训队互测 Day 1」完美的队列(分块+双指针)

    点此看题面 大致题意: 让你维护\(n\)个有限定长度的队列,每次区间往队列里加数,求每次加完后的队列里剩余元素种类数. 核心思路 这道题可以用分块+双指针去搞. 考虑求出每个操作插入的元素在队列中被 ...

  8. ubuntu误删home目录

    今天第一次写shell脚本,一不小心把home目录全给删除了. 解决方案: 先把手打上二十大板!!! [root@myshell ~]#mkdir /home/test01             / ...

  9. POJ 1423 斯特林

    题意:进制问题 分析: 打表,但是要用不能 long long 型,超内存. n! = log_{10}\sqrt{2{\pi}n}*(\frac{n}e)^n 精度要求 #include <c ...

  10. iOS 代码混淆--pch实现

    之前实现代码的混淆一般是使用sh脚本,不过也是需要把一写需要混淆的方法写到一个文件中(除非是使用特定的命名规范统一混淆), 现在发现,实现代码的混淆pch 文件就可以轻松完成! 1,在新建的工程中 创 ...