MySQLerの七つ道具
2016/11/26
yoku0825
第18回 中国地⽅DB勉強会 in 広島
\こんにちは/
yoku0825@GMOメディア株式会社
オラクれない-
ポスグれない-
マイエスキューエる-
⽣息域
Twitter: @yoku0825-
Blog: ⽇々の覚書-
MyNA ML: ⽇本MySQLユーザ会-
MySQL Casualʼs Slack: MySQL Casual-
1/79
MySQLer七つ道具
pt-query-digest1.
EXPLAIN2.
PMP for Cacti3.
innotop4.
SHOW PROFILE5.
performance̲schema & sys6.
???7.
2/79
MySQLer七つ道具
pt-query-digest1.
EXPLAIN2.
PMP for Cacti3.
innotop4.
SHOW PROFILE5.
performance̲schema & sys6.
???7.
3/79
pt-query-digest
みんなだいすきPercona Toolkitの⼈気No.1
スローログをまとめて⾒やすくしてくれる
⼤⽂字⼩⽂字、⽂字列定数と数値定数をノーマライズして「ダイジェ
スト」ごとに集約
-
4/79
先頭のセクション
$ pt-query-digest /path/to/slowlog
..
# Time range: 2016-03-16 17:29:32 to 2016-11-22 11:37:24
# Attribute total min max avg 95% stddev medi
an
# ============ ======= ======= ======= ======= ======= ======= =====
==
# Exec time 45155s 500ms 117s 3s 7s 9s 640
ms
# Lock time 2s 29us 14ms 110us 176us 136us 93
us
# Rows sent 156.96M 0 5.85M 10.33k 54.03k 74.89k 0.
99
# Rows examine 36.18G 0 26.40M 2.38M 22.38M 5.41M 298.0
6k
# Rows affecte 0 0 0 0 0
0 0
# Bytes sent 9.86G 0 362.91M 664.55k 4.26M 4.87M 1.0
9k
# Query size 3.29M 25 24.47k 221.80 346.17 425.46 136.
99
..
5/79
先頭のセクション
まああんま⾒ない
6/79
ダイジェスト⼀覧
# Profile
# Rank Query ID Response time Calls R/Call V/M It
em
# ==== ================== ================ ===== ======= ===== ==
=========
# 1 0x15E7E7E2F486896A 16739.1308 37.1% 382 43.8197 0.76 SE
LECT table1 table2 table3
# 2 0x223A9E1EC454F977 10883.7272 24.1% 270 40.3101 5.94 SE
LECT table1 table3
# 3 0xAF335DE1A49E8218 2909.3875 6.4% 5542 0.5250 0.00 SE
LECT table4
# 4 0x180720D51CB2E890 2044.8649 4.5% 1451 1.4093 0.07 SE
LECT table5
..
7/79
ダイジェスト⼀覧
デフォルトでは「トータルでかかった時間」の降順
--order-by で変えられるデフォルトは “Query̲time:sum”
書き⽅にちょっとクセがある
Query̲time:max
Query̲time:sum
Rows̲examined:max
bytes:sum とか
-
8/79
ダイジェストごと、前半
Query 1: 0.00 QPS, 0.01x concurrency, ID 0x15E7E7E2F486896A at byte 6304792
# This item is included in the report because it matches --limit.
# Scores: V/M = 0.76
# Time range: 2016-11-01 14:02:59 to 2016-11-22 11:37:24
# Attribute pct total min max avg 95% stddev median
# ============ === ======= ======= ======= ======= ======= ======= =======
# Count 2 382
# Exec time 37 16739s 37s 100s 44s 52s 6s 40s
# Lock time 2 50ms 70us 395us 131us 152us 25us 125us
# Rows sent 0 1.87k 5 5 5 5 0 5
# Rows examine 27 9.78G 26.05M 26.40M 26.22M 25.91M 0 25.91M
# Rows affecte 0 0 0 0 0 0 0 0
# Bytes sent 0 311.36k 825 840 834.63 833.10 7.50 833.10
# Query size 6 228.65k 611 614 612.93 592.07 0 592.07
9/79
ダイジェストごと、前半
1⾏目に ID 0x.. があるので、ダイジェスト⼀覧から検索で
⾶んでくるとよし
Time range を⾒ないと、実は半年前に撲滅されたクエリー
を⼀⽣懸命EXPLAINする⽻目に遭ったり
単発のクエリーが⼤きくて累計 Exec time が⼤きくなってる
のか、満遍なく出続けているのか
anemo eat erも便利だよ-
Rows examine / Rows_sent
GROUP BYを除くと、⽐率が1に近く低いほど理想-
Lock time はInnoDBではアテにならないので注意
10/79
ダイジェストごと、後半
# Query_time distribution
# 1us
# 10us
# 100us
# 1ms
# 10ms
# 100ms
# 1s
# 10s+ ########################################################
########
# Tables
..
# EXPLAIN /*!50100 PARTITIONS*/
SELECT ..
11/79
ダイジェストごと、後半
クエリーごとにバラつきがあるか︖
バラついているなら、カーディナリティーの悪戯か、それともキャッ
シュの具合か
特にInnoDB圧縮を使ってる場合、バッファプールミスヒットやテーブルキャッシュミ
スヒットのコストは⼤きい
-
均等に遅いなら、それはクソクエリーかな-
ただし pt-query-digest がそもそも、スローログに載っているヤーツ
しか⾒られない以上、まともな速度で応答を返しているヤーツは検出
されない
-
最後の⾏はEXPLAIN⽤に1⾏、集約してないやつを引っこ抜
いてくれるだけ
オプションによっては⾃動でEXPLAINまでかけてくれる-
12/79
pt-query-digestと上⼿く付き合うコツ
--since オプションはほぼ必須
--since オプションでもログは舐めてしまうので、⼤きなログを⾷わ
すのであれば tail -50000 slow.log | pt-query-digest とパイプで
⾷わせるのも⼿
-
「膨⼤で⾒にくいスローログの塊を、認識しやすいチャンク
にまとめる」
--group-by=tables からの --group-by=fingerprint --
filter='$events->{fingerprint} =~ /sテーブル名s/' とか
-
13/79
with Anemometer
pt-query-digest の出⼒結果を可視化するツール
pt-query-digest の結果をMySQLに⼊れる機能(--history,
--review)をそのまま使ってる
box/Anemometer: Box SQL Slow Query Monitor
14/79
Anemometerの弱点
テーブル上UNIQUE KEY (hostname_max, checksum, ts_min,
ts_max)で、Anemometerはts_minでプロットするため、そ
のクエリーがts_minに集中したことになってしまう。
mysql> SELECT * FROM global_query_review_history LIMIT 1G
*************************** 1. row ***************************
hostname_max: xxx
db_max: xxx
checksum: 1233945238822708500
sample: xxx
ts_min: 2015-09-14 11:32:12
ts_max: 2015-10-28 15:51:01
ts_cnt: 31
Query_time_sum: 651.778
Query_time_min: 2.07993
Query_time_max: 197.678
15/79
Anemometerの弱点
⽇次で pt-query-digest を回している程度だと、⽇単位までし
か分解できない
16/79
anemo eat er
スローログをスプリットして pt-query-digest を呼びまくる
1分ぶんずつ pt-query-digest に⾷わせれば、ts_min と ts_max の差
は最⼤でも1分
-
AnemometerをDockerコンテナーとして起動する-
既存のAnemometerがあれば単にスローログを分割して⾷わせる pt-
query-digest のラッパーとして呼べる
-
17/79
with anemo eat er
1分単位でプロットできる
18/79
anemo eat er
リアルタイムでなくてもいい
スロークエリーのリアルタイム通知は別の⽅法でしてる-
グラフで⾒られれば数分前の情報であっても全然構わない-
リアルタイムを捨てて
保存期間を考えない
スローログが残っている限りの情報を、最初から、最後まで⾒られる
-
⾒るかどうかもわからないグラフのために常時リソースを割かなくて
いい
⾒たく / ⾒せたく なったら起動、⾒終わったら停⽌
-
19/79
anemo eat er
現在のところ docker と pt-query-digest はホストにインス
トールしておかないとダメ
$ git clone https://github.com/yoku0825/anemoeater
$ cd anemoeater
$ ./anemoeater slow_log_file
Docker container starts with 172.17.0.43.
URL will be http://xxxx:32780/anemometer
20/79
pt-query-digest
だいたいこんな感じでDailyの動きをメールで⾶ばしてる
気になったら anemo eat erで⾒る
$ pt-query-digest --since=$(date -d yesterday "+%Y-%m-%d") /pat
h/to/slowlog | awk '/^# Overall:/{print $3, $5}'
822 4
21/79
MySQLer七つ道具
pt-query-digest1.
EXPLAIN2.
PMP for Cacti3.
innotop4.
SHOW PROFILE5.
performance̲schema & sys6.
???7.
22/79
EXPLAIN
今更なのでEXTENDEDの話しかしないよ
23/79
目XPLAIN
出来る⼈︖
24/79
Please 目XPLAIN Me
SELECT DISTINCT
T.c_month,
T.unique_id
FROM
(SELECT A.a_id, DATE_FORMAT(C.datetime, '%Y%m') AS c_month, C.u
nique_id
FROM table_2 AS C
LEFT OUTER JOIN table_1 AS A
ON (CAST(C.session_id AS CHAR) = A.another_id AND C.unique_id
= A.unique_id)
WHERE C.unique_id = 0x333132 AND C.unique_id <= 260006385 AND
C.datetime < TIMESTAMPADD(DAY, -180, CURDATE())
) AS T
WHERE
T.another_id IS NULL
25/79
実はこれ、5.6
と5.7で実⾏計
画が違う
26/79
5.6
*************************** 1. row ***************************
id: 1
select_type: PRIMARY
table: <derived2>
type: ref
possible_keys: <auto_key0>
key: <auto_key0>
key_len: 35
ref: const
rows: 10
Extra: Using where; Using temporary
*************************** 2. row ***************************
id: 2
select_type: DERIVED
table: C
type: range
possible_keys: PRIMARY,idx_xxx,idx_yyy_zzz
key: PRIMARY
key_len: 8
ref: NULL
rows: 12130512
Extra: Using where
*************************** 3. row ***************************
id: 2
select_type: DERIVED
table: A
type: eq_ref
possible_keys: PRIMARY,idx_xxx_yyy,idx_xxx_aaa_ccc,idx_xxx_ddd
key: PRIMARY
key_len: 68
ref: func,const
rows: 1
Extra: Using where; Using index
27/79
5.7
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: C
partitions: NULL
type: range
possible_keys: PRIMARY,idx_xxx,idx_yyy_zzz
key: PRIMARY
key_len: 8
ref: NULL
rows: 12675660
filtered: 5.97
Extra: Using where; Using temporary
*************************** 2. row ***************************
id: 1
select_type: SIMPLE
table: A
partitions: NULL
type: eq_ref
possible_keys: PRIMARY,idx_xxx_yyy,idx_xxx_aaa_ccc,idx_xxx_ddd
key: PRIMARY
key_len: 68
ref: func,const
rows: 1
filtered: 100.00
Extra: Using where; Not exists; Using index
28/79
5.6
mysql> SHOW WARNINGSG
*************************** 1. row ***************************
Level: Note
Code: 1003
Message: /* select#1 */ select distinct `t`.`c_month` AS `c_month
`,`t`.`unique_id` AS `unique_id` from (/* select#2 */ select `sch
ema`.`a`.`another_id` AS `another_id`,date_format(`schema`.`c`.`d
atetime`,'%Y%m') AS `c_month`,`schema`.`c`.`unique_id` AS `unique
_id` from `schema`.`table_2` `c` left join `schema`.`table_1` `a
` on(((`schema`.`a`.`unique_id` = 0x333132) and (cast(`schema`.`c
`.`SESSION_ID` as char charset sjis) = `schema`.`a`.`another_id`)
)) where ((`schema`.`c`.`unique_id` = 0x333132) and (`schema`.`c
`.`UNIQUE_ID` <= 260006385) and (`schema`.`c`.`datetime` < <cache
>((curdate() + interval -(180) day))))) `t` where isnull(`t`.`ano
ther_id`)
1 row in set (0.00 sec)
29/79
5.7
> SHOW WARNINGSG
*************************** 1. row ***************************
Level: Note
Code: 1003
Message: /* select#1 */ select distinct date_format(`schema`.`c`.
`OCCUR_DATE`,'%Y%m') AS `c_month`,`schema`.`c`.`unique_id` AS `un
ique_id` from `schema`.`table_2` `c` left join `schema`.`table_1
` `a` on(((`schema`.`a`.`unique_id` = 0x333132) and (cast(`schema
`.`c`.`SESSION_ID` as char charset sjis) = `schema`.`a`.`another_
id`))) where ((`schema`.`c`.`unique_id` = 0x333132) and isnull(`s
chema`.`a`.`another_id`) and (`schema`.`c`.`UNIQUE_ID` <= 2600063
85) and (`schema`.`c`.`OCCUR_DATE` < <cache>((curdate() + interva
l -(180) day))))
30/79
EXPLAIN EXTENDED
5.7からはデフォルトでEXTENDEDがついてくる
EXPLAIN直後に SHOW WARNINGS でオプティマイザーが最適化した後
のクエリーが⾒える
-
想像したのと違う遅くなり⽅ をしたらEXTENDED⾒た⽅が
良い
特に5.6の蝉ジョインとか蝉ジョインとか蝉ジョインとか-
MySQL :: MySQL 5.6 リファレンスマニュアル :: 8.8.3
EXPLAIN EXTENDED 出⼒フォーマット
31/79
MySQLer七つ道具
pt-query-digest1.
EXPLAIN2.
PMP for Cacti3.
innotop4.
SHOW PROFILE5.
performance̲schema & sys6.
???7.
32/79
PMP(Percona Monitoring Plugins) for Cacti
別に for Zabbixでもいいと思う
単にウチはもともとCactiを使っていたからというだけ
33/79
PMP for Cacti
rrdtoolだから容量効率は素晴らしい
rrdtoolだから丸め誤差は厳しい
CactiそのものがWEBからポチポチするインターフェースな
のつらい
ss̲get̲mysql̲stats.php ⾃体はPHPで、頑張って⾊々パー
スしてるので、ホゲろうと思えばホゲれる
けど、それならPerlで書きたい-
34/79
Data Input Methodのデフォルトを⼀気にSQLで書き換
えるとか
mysql> UPDATE data_input_fields JOIN data_input_data ON data_input_fields.id
= data_input_data.data_input_field_id JOIN data_input ON data_input_fields.d
ata_input_id = data_input.id
-> SET data_input_data.value = 'pmp' WHERE data_input.name LIKE 'Percon
a %' AND data_input_fields.name = 'Username';
mysql> UPDATE data_input_fields JOIN data_input_data ON data_input_fields.id
= data_input_data.data_input_field_id JOIN data_input ON data_input_fields.d
ata_input_id = data_input.id
-> SET data_input_data.value = 'pmp_pass' WHERE data_input.name LIKE 'Pe
rcona %' AND data_input_fields.name = 'Password';
mysql> UPDATE data_input_fields JOIN data_input_data ON data_input_fields.id
= data_input_data.data_input_field_id JOIN data_input ON data_input_fields.d
ata_input_id = data_input.id
-> SET data_input_data.value = '3306', data_input_data.t_value = 'on' WH
ERE data_input.name LIKE 'Percona %' AND data_input_fields.name = 'Port';
35/79
Device追加する時にポートを⼀⻫に変えるブックマーク
レットだとか
javascript:void((function(elems,port){for(var p in elems){elems[p
].value=port}})(document.querySelectorAll('input[type=text]'),pro
mpt('port','3306')))
(c) irok
36/79
みんなどうし
てるんだろう
37/79
PMP for Cacti
やっぱり視認性だいじ
絶対値に惑わされない
問題が起きていなくてもたまには⾒る
たまには⻑い期間で⾒る
使いづらいものはユーティリティー作っちゃえばいいと思う
38/79
MySQLer七つ道具
pt-query-digest1.
EXPLAIN2.
PMP for Cacti3.
innotop4.
SHOW PROFILE5.
performance̲schema & sys6.
???7.
39/79
innotop
みんな⼤好き、topライクに SHOW PROCESSLIST を表⽰して
くれるinnotop
地味に “M” (Replication Status) も便利
なんとMSR対応してるんだぜ
-
“L” (InnoDB Locks) とか-
“T” (InnoDB Transaction) とか-
pt-osc してる間だと “D” (InnoDB Deadlocks) を眺めることもある-
tmuxでばっちんばっちんターミナル割って、 dstat とか流
しながら⾒るのが好き
40/79
innotop
41/79
innotop
地味に機能は多いけど今のバージョンだと表⽰されない項目
がたまにある
旧バージョンのサポート切れば楽なんだけど…と思ったり思わなかっ
たり
-
ALTER TABLE や percona-toolkit で重いことやる時のおとも
に最適
“d” で表⽰間隔の変更。0.1とかやるとたのしい-
ただし万能感を期待しない-
“Q” => “K” => “T” => “k” (killステートメント) のコンボで詰まっ
てるのを殺すくらい
-
42/79
innotop
中⾝は結構スパゲティ
最近メンテナンス遅め
ちょっと⾊々事情が-
⽇々の覚書: innotopのその後 2016年6⽉-
43/79
MySQLer七つ道具
pt-query-digest1.
EXPLAIN2.
PMP for Cacti3.
innotop4.
SHOW PROFILE5.
performance̲schema & sys6.
???7.
44/79
SHOW PROFILE
MySQLの組み込みプロファイラー
「そのクエリーが実⾏されていた期間、どのStatus(SHOW
PROCESSLIST で “State” と表⽰されているもの)にどのくら
いの時間かかったか
使うのが超簡単
45/79
SHOW PROFILE
mysql> SET @@profiling= 1;
Query OK, 0 rows affected, 1 warning (0.01 sec)
mysql> ..;
mysql> SHOW PROFILE;
+----------------------+----------+
| Status | Duration |
+----------------------+----------+
| starting | 0.000206 |
| checking permissions | 0.000024 |
| Opening tables | 0.000039 |
| init | 0.000089 |
| System lock | 0.000027 |
| optimizing | 0.000037 |
| statistics | 0.000245 |
| preparing | 0.000058 |
| Creating tmp table | 0.000119 |
| Sorting result | 0.000023 |
| executing | 0.000019 |
| Sending data | 2.619037 |
| Creating sort index | 0.000821 |
| end | 0.000014 |
| removing tmp table | 0.000017 |
| end | 0.000013 |
| query end | 0.000015 |
| closing tables | 0.000022 |
| freeing items | 0.000028 |
| logging slow query | 0.000109 |
| cleaning up | 0.000013 |
+----------------------+----------+
21 rows in set (0.00 sec)
46/79
SHOW PROFILE
組み込みだから使うのは超簡単
プロファイルを「どう解析するか」はまた別の問題
ざっと⾒てわかりやすいところに時間がかかってたらつぶせ
る…くらいのノリ
再現性がないとつらい
47/79
SHOW PROFILE S
mysql> SHOW PROFILES;
+----------+-------------+-------------------------------------------------------------------------------+
| Query_ID | Duration | Query |
+----------+-------------+-------------------------------------------------------------------------------+
| 1 | 7.56061200 | SELECT * FROM t1 WHERE val IN (SELECT val FROM t2 WHERE num BETWEEN 1 AND 10) |
| 2 | 8.00373925 | DELETE FROM t1 WHERE num > 1000 |
| 3 | 1.05841250 | DELETE FROM t1 WHERE num > 100 |
| 4 | 33.97938100 | DELETE FROM t2 WHERE num > 100 |
| 5 | 1.09654200 | DELETE FROM t2 WHERE num > 40 |
| 6 | 0.03032175 | DELETE FROM t1 WHERE num > 40 |
| 7 | 0.00410725 | explain SELECT * FROM t2 JOIN t1 USING(val) WHERE t2.num = 1 |
| 8 | 0.01773500 | SELECT * FROM t1 WHERE val IN (SELECT val FROM t2 WHERE num BETWEEN 1 AND 10) |
| 9 | 0.02148750 | DELETE FROM t1 WHERE num > 30 |
| 10 | 0.27967925 | DELETE FROM t2 WHERE num > 30 |
| 11 | 0.00826075 | SELECT * FROM t1 WHERE val IN (SELECT val FROM t2 WHERE num BETWEEN 1 AND 10) |
+----------+-------------+-------------------------------------------------------------------------------+
11 rows in set (0.01 sec)
48/79
SHOW PROFILE FOR QUERY ..
mysql> SHOW PROFILE FOR QUERY 4;
+------------------------------+-----------+
| Status | Duration |
+------------------------------+-----------+
| starting | 0.007228 |
| checking permissions | 0.000302 |
| Opening tables | 0.001042 |
| System lock | 0.000030 |
| init | 0.006702 |
| updating | 33.930371 |
| end | 0.000923 |
| Waiting for query cache lock | 0.000013 |
| end | 0.002784 |
| query end | 0.024151 |
| closing tables | 0.000430 |
| freeing items | 0.000809 |
| logging slow query | 0.000006 |
| logging slow query | 0.004583 |
| cleaning up | 0.000009 |
+------------------------------+-----------+
15 rows in set (0.01 sec)
49/79
SHOW PROFILE
MySQL 5.6でdeprecated
代替として performance_schema.events_stages_* と
events_statements_* が案内されている…けど
-
@@profiling はセッション単位に対して、p̲sはセッション単位の調
整がちょっと難しい
-
⼀応、MySQL 8.0.0現在でもまだ使える
50/79
MySQLer七つ道具
pt-query-digest1.
EXPLAIN2.
PMP for Cacti3.
innotop4.
SHOW PROFILE5.
performance̲schema & sys6.
???7.
51/79
performance̲schema(p̲s)
パフォーマンスモニタリング専⽤のストレージエンジン
MySQL 5.6から真っ当に使えるようになってる
吊るしのデフォルトではONになってる-
計測する項目も「だいたい必要になりそうなところ」だけがONになっ
てるので、必要になるまではそのまま使えばOK
-
メモリーを⾷うのは相変わらず
デフォルトがautosizeなので、気になる場合は固定値を決め打つ-
しかも5.7のデフォルトが auto re size になりやがった。。-
52/79
p_s.setup_*
mysql> SHOW TABLES FROM performance_schema LIKE 'setup_%';
+-----------------------------------------+
| Tables_in_performance_schema (setup_%) |
+-----------------------------------------+
| setup_actors |
| setup_consumers |
| setup_instruments |
| setup_objects |
| setup_timers |
+-----------------------------------------+
5 rows in set (0.00 sec)
53/79
p_s.setup_consumers
mysql> SELECT * FROM setup_consumers;
+----------------------------------+---------+
| NAME | ENABLED |
+----------------------------------+---------+
| events_stages_current | NO |
| events_stages_history | NO |
| events_stages_history_long | NO |
| events_statements_current | YES |
| events_statements_history | YES |
| events_statements_history_long | NO |
| events_transactions_current | NO |
| events_transactions_history | NO |
| events_transactions_history_long | NO |
| events_waits_current | NO |
| events_waits_history | NO |
| events_waits_history_long | NO |
| global_instrumentation | YES |
| thread_instrumentation | YES |
| statements_digest | YES |
+----------------------------------+---------+
15 rows in set (0.00 sec)
54/79
p_s.setup_instruments
mysql> SELECT SUBSTRING_INDEX(`name`, '/', 2) AS short_name, ANY_VALUE(name) AS example, SUM(ENABLED = 'YES') AS enabled, SUM(ENABLED
= 'NO') AS disabled FROM setup_instruments GROUP BY short_name;
+---------------------------+-----------------------------------------------------+---------+----------+
| short_name | example | enabled | disabled |
+---------------------------+-----------------------------------------------------+---------+----------+
| idle | idle | 1 | 0 |
| memory/archive | memory/archive/FRM | 0 | 2 |
| memory/blackhole | memory/blackhole/blackhole_share | 0 | 1 |
| memory/client | memory/client/mysql_options | 0 | 7 |
| memory/csv | memory/csv/TINA_SHARE | 0 | 5 |
| memory/federated | memory/federated/FEDERATED_SHARE | 0 | 1 |
| memory/innodb | memory/innodb/adaptive hash index | 0 | 85 |
| memory/keyring | memory/keyring/KEYRING | 0 | 1 |
| memory/memory | memory/memory/HP_SHARE | 0 | 4 |
| memory/myisam | memory/myisam/MYISAM_SHARE | 0 | 21 |
| memory/myisammrg | memory/myisammrg/MYRG_INFO | 0 | 2 |
| memory/mysys | memory/mysys/max_alloca | 0 | 21 |
| memory/partition | memory/partition/ha_partition::file | 0 | 3 |
| memory/performance_schema | memory/performance_schema/mutex_instances | 70 | 0 |
| memory/sql | memory/sql/Locked_tables_list::m_locked_tables_root | 0 | 152 |
| memory/vio | memory/vio/ssl_fd | 0 | 3 |
| stage/innodb | stage/innodb/alter table (end) | 8 | 0 |
| stage/mysys | stage/mysys/Waiting for table level lock | 0 | 1 |
| stage/sql | stage/sql/After create | 1 | 119 |
| statement/abstract | statement/abstract/Query | 3 | 0 |
| statement/com | statement/com/Sleep | 32 | 0 |
| statement/scheduler | statement/scheduler/event | 1 | 0 |
| statement/sp | statement/sp/stmt | 16 | 0 |
| statement/sql | statement/sql/select | 141 | 0 |
| transaction | transaction | 0 | 1 |
| wait/io | wait/io/file/sql/map | 55 | 3 |
| wait/lock | wait/lock/table/sql/handler | 1 | 1 |
| wait/synch | wait/synch/mutex/sql/TC_LOG_MMAP::LOCK_tc | 0 | 257 |
+---------------------------+-----------------------------------------------------+---------+----------+
28 rows in set (0.01 sec)
55/79
統計情報へのアクセス
mysql> SHOW TABLES;
..
| events_stages_summary_by_account_by_event_name |
| events_stages_summary_by_host_by_event_name |
..
| memory_summary_by_thread_by_event_name |
| memory_summary_by_user_by_event_name |
| memory_summary_global_by_event_name |
..
| replication_applier_configuration |
| replication_applier_status |
..
56/79
p̲s⾃体のモニタリング
mysql> SHOW ENGINE PERFORMANCE_SCHEMA STATUS;
+--------------------+----------------------------------------------------------
---+----------+
| Type | Nam
e | Status |
+--------------------+----------------------------------------------------------
---+----------+
| performance_schema | events_waits_current.siz
e | 176 |
| performance_schema | events_waits_current.coun
t | 1536 |
| performance_schema | events_waits_history.siz
e | 176 |
| performance_schema | events_waits_history.coun
t | 2560 |
| performance_schema | events_waits_history.memor
y | 450560 |
..
| performance_schema | performance_schema.memor
y | 94739320 |
+--------------------+----------------------------------------------------------
---+----------+
229 rows in set (0.00 sec)
57/79
sys
p̲sの情報を⾒やすくするためのビューやストアドファンク
ション、ストアドプロシージャ
名前空間として sys スキーマを使うのでそう呼ぶことも
performance_schema = OFF の状態ではほとんどからっぽ
MySQL 5.7では最初から導⼊済み
MySQL 5.6にも対応
GitHubのmysql-sysリポジトリー からインストール-
58/79
sysのインストール(5.6向け)
$ git clone https://github.com/mysql/mysql-sys.git
Initialized empty Git repository in /root/mysql-sys/.git/
remote: Counting objects: 3009, done.
remote: Total 3009 (delta 0), reused 0 (delta 0), pack-reused 3008
Receiving objects: 100% (3009/3009), 1.17 MiB | 466 KiB/s, done.
Resolving deltas: 100% (1768/1768), done.
$ cd mysql-sys
$ mysql -uroot -p < sys_56.sql
$ mysql -uroot -p
mysql> SHOW DATABASES;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
+--------------------+
4 rows in set (0.01 sec)
59/79
sys.statement_analysis
p_s.events_statements_summary_by_digest のビュー
超⾒やすい
これのためだけに p̲s有効にする価値がある
60/79
sys.statement_analysis
mysql> SELECT * FROM statement_analysisG
..
*************************** 2. row ***************************
query: SELECT `c` FROM `sbtest1` WHERE `id` = ?
db: sbtest
full_scan:
exec_count: 23890
err_count: 0
warn_count: 0
total_latency: 2.36 s
max_latency: 521.15 us
avg_latency: 98.74 us
lock_latency: 778.65 ms
rows_sent: 23890
rows_sent_avg: 1
rows_examined: 23890
rows_examined_avg: 1
rows_affected: 0
rows_affected_avg: 0
tmp_tables: 0
tmp_disk_tables: 0
rows_sorted: 0
sort_merge_passes: 0
digest: 80295d1d2720d4515b05d648e8caa82f
first_seen: 2016-07-12 17:04:40
last_seen: 2016-07-12 17:04:53
..
61/79
sys.innodb_lock_waits
いわゆるSH2さんの アレ とほぼ同等の機能
これは i̲s のビューなので、p̲sが無効でもフツーに⾒られ
る
バンドルされて便利になったという感じ
62/79
sys.innodb_lock_waits
mysql57> SELECT * FROM innodb_lock_waitsG
*************************** 1. row ***************************
wait_started: 2016-07-12 17:49:06
wait_age: 00:00:13
wait_age_secs: 13
locked_table: `d1`.`user`
locked_index: PRIMARY
locked_type: RECORD
waiting_trx_id: 8063
waiting_trx_started: 2016-07-12 17:49:06
waiting_trx_age: 00:00:13
waiting_trx_rows_locked: 1
waiting_trx_rows_modified: 0
waiting_pid: 320
waiting_query: SELECT * FROM user LIMIT 3 FOR UPDATE
waiting_lock_id: 8063:146:3:2
waiting_lock_mode: X
blocking_trx_id: 8062
blocking_pid: 321
blocking_query: NULL
blocking_lock_id: 8062:146:3:2
blocking_lock_mode: X
blocking_trx_started: 2016-07-12 17:49:06
blocking_trx_age: 00:00:13
blocking_trx_rows_locked: 3
blocking_trx_rows_modified: 0
sql_kill_blocking_query: KILL QUERY 321
sql_kill_blocking_connection: KILL 321
1 row in set (0.01 sec)
63/79
sys.ps_truncate_all_tables
ストアド
p̲s は起動時から統計情報を累積するが、それをリセットす
るにはp̲sの各テーブルに対してTRUNCATEが必要
それを全部まとめてやってくれる、ただそれだけなんだけど
便利なストアド
mysql> CALL sys.ps_truncate_all_tables(0);
+---------------------+
| summary |
+---------------------+
| Truncated 44 tables |
+---------------------+
1 row in set (0.01 sec)
Query OK, 0 rows affected (0.01 sec)
64/79
sys.x$*
x$ で始まるビューは、 x$ のない他のビューと対になってい
る
フツーの⽅は、[kMG]B をまとめたり [num]s をまとめた
りしてくれるが、そうすると⽂字列になっちゃうのでソート
に不便
そんな時、 x$ のビューは何の整形もしないので…ってこと
だと思う
でもナノ秒単位とか正直つらいので、ソートだけ x$ でやって digest
カラムとかでフツーのビューとJOINした⽅がいいと思う
-
65/79
MySQLer七つ道具
pt-query-digest1.
EXPLAIN2.
PMP for Cacti3.
innotop4.
SHOW PROFILE5.
performance̲schema & sys6.
???7.
66/79
Do you
know
“Dimitri”?
67/79
Dimitri KRAVTCHUK
68/79
Dimitriおじさん says
69/79
Dimitriおじさん says
70/79
Dimitriおじさん says
71/79
エコシステム
たとえば MariaDB, Percona Server
たとえば MHA for MySQL, HandlerSocket
たとえば ⽇本MySQLユーザ会, MySQL Casual
たとえば Oracle
72/79
USE YOUR
BRAIN
73/79
but/and
74/79
YOU are
not alone.
75/79
2年前
76/79
みなさんのご参加をお待ちしております :)
MyNA ML: ⽇本MySQLユーザ会
MySQL Casualʼs Slack: MySQL Casual
77/79
Advent Calendarのおさそい
まだまだお席に余裕がございます
具体的には 20 名様ほどお⼊りいただけます-
@soudai1025-
@kkkida̲twtr-
@kamipo-
MySQL Casual Advent Calendar 2016 - Qiita
78/79
Questions
and/or
Suggestions?
79/79

MySQLerの7つ道具