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. oracle学习篇十一:视图

    视图是存储的查询定义. 1. 创建视图的语法如下: Create [OR REPLACE] [FORCE | NOFORCE] VIEW view_name[(alias,alias,...)] AS ...

  2. 安装redis服务端

    1. redis服务端和客户端的安装 [root@xxx ~]# cd /usr/local/src [root@xxx src]# wget http://download.redis.io/rel ...

  3. 洛谷P1941 飞扬的小鸟(背包 dp)

    题意 题目链接 Sol 很显然的dp,设\(f[i][j]\)表示第\(i\)个位置,高度为\(j\)的最小步数 向上转移的时候是完全背包 向下转移判断一下就可以 #include<bits/s ...

  4. HTML标签 链接 随笔3

    4-1 <a>标签  网页链接 使用<a>标签可实现超链接,它在网页制作中可以说是无处不在,只要有链接的地方,就会有这个标签. 语法: <a href="目标网 ...

  5. jQuery之检测分析纠错------地狱的镰刀

    1. 答: 或者: $(selector).eq(0).hide(); 解答:get() 方法获得由选择器指定的 DOM 元素. 2. 答: 3, 答1: 答2: 4. slideDown()方法格式 ...

  6. Linux在Tomcat下部署JavaWeb项目

    一.Linux快速部署War包操作 1.先关闭Tomcat /home/java/tomcat8/bin/shutdown.sh 注意:进入tomcat bin目录下操作 2.进入War包存放目录(可 ...

  7. .NET开源工作流RoadFlow-表单设计-HTML编辑器

    roadflow目前采用的html编辑器为ueditor编辑器(和表单设计器的编辑器相同). 绑定字段:与数据表的某个字段对应. 宽度:编辑器的宽度. 高度:编辑器的高度. 运行效果如下:

  8. ERP设计之系统基础管理(BS)-日志模块设计(转载)

    原文地址:8.ERP设计之系统基础管理(BS)-日志模块设计作者:ShareERP 日志模块基本要素包括: 用户会话.登录.注销.模块加载/卸载.数据操作(增/删/改/审/弃/关等等).数据恢复.日志 ...

  9. 《ArcGIS Runtime SDK for Android开发笔记》——(11)、ArcGIS Runtime SDK常见空间数据加载

    ArcGIS Runtime SDK for Android 支持多种类型空间数据源.每一种都提供了相应的图层来直接加载,图层Layer是空间数据的载体,其主要继承关系及类型说明如下图所示: 转载请注 ...

  10. <meta name="viewport" content="width=device-width, initial-scale=1.0">理解

    ViewPort <meta>标记用于指定用户是否可以缩放Web页面,如果可以,那么缩放到的最大和最小缩放比例是什么.使用ViewPort <meta>标记还表示文档针对移动设 ...