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. lua load

    load (chunk [, chunkname [, mode [, env]]]) 加载一个代码块. 如果 chunk 是一个字符串,代码块指这个字符串. 如果 chunk 是一个函数, load ...

  2. scss-@media

    首先回顾下css3中的@media 定义和使用: 使用 @media 查询,你可以针对不同的媒体类型定义不同的样式. @media 可以针对不同的屏幕尺寸设置不同的样式,特别是如果你需要设置设计响应式 ...

  3. C语言入门(一)环境搭建

    1. 下载Code::Blocks(源文本编辑器) 2. 下载编译器MinGW(或者下载好自带编译器的codeblocks) http://jingyan.baidu.com/article/c843 ...

  4. solidity语言8

    输入参数 pragma solidity ^0.4.16; contract Simple { function taker(uint _a, uint _b) public pure { // do ...

  5. MFC 鼠标事件

    1. 新建项目 项目名称:MFCBaseMessage 2. 选择基本对话框模式,如图 ,点击完成3. 最终如图 4.右键添加类向导   5.添加鼠标事件 6.在ON_LButtonDown添加如下代 ...

  6. Perl实用中文处理步骤(修改版)

    发信人: FenRagwort (泽), 信区: Perl标  题: Perl实用中文处理步骤(修改版)发信站: 水木社区 (Mon Feb 14 12:52:14 2011), 转信 (修改版 感谢 ...

  7. 到底哪种类型的错误信息会阻止business transaction的保存

    当试图在CRM WebUI保存一个business transaction比如Opportunity时,可能会遇到各种各样的错误消息.有的错误消息会阻止Business transaction被sav ...

  8. 数据库-identifying 与non-identifying realtionship 区别

    MySQL Workbench 或者是 E-RWin等进行数据库建模时,通常会对数据表进行关联操作,即设置表与表之间的关系 1:1 1:n m:n,而它们具有 identifying realtion ...

  9. 《编程导论(Java)·9.3.1回调·3》回调的实现

    版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/yqj2065/article/details/31441221 接<9.3.1Java回调 · ...

  10. MySQL:数据库入门篇4

    1. 视图 创建视图 create view 视图名字 as 查询sql语句; drop view 视图名字; alter view 视图名字 as 查询sql语句; 2. 触发器 1. 插入事件触发 ...