Se ha denunciado esta presentación.
Utilizamos tu perfil de LinkedIn y tus datos de actividad para personalizar los anuncios y mostrarte publicidad más relevante. Puedes cambiar tus preferencias de publicidad en cualquier momento.
MySQLerの七つ道具
2016/11/26
yoku0825
第18回 中国地⽅DB勉強会 in 広島
\こんにちは/
yoku0825@GMOメディア株式会社
オラクれない-
ポスグれない-
マイエスキューエる-
⽣息域
Twitter: @yoku0825-
Blog: ⽇々の覚書-
MyNA ML: ⽇本MySQLユーザ会-
MySQL C...
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 ...
先頭のセクション
まああんま⾒ない
6/79
ダイジェスト⼀覧
# Profile
# Rank Query ID Response time Calls R/Call V/M It
em
# ==== ================== ================ ===== =...
ダイジェスト⼀覧
デフォルトでは「トータルでかかった時間」の降順
--order-by で変えられるデフォルトは “Query̲time:sum”
書き⽅にちょっとクセがある
Query̲time:max
Query̲time:sum
Rows...
ダイジェストごと、前半
Query 1: 0.00 QPS, 0.01x concurrency, ID 0x15E7E7E2F486896A at byte 6304792
# This item is included in the rep...
ダイジェストごと、前半
1⾏目に ID 0x.. があるので、ダイジェスト⼀覧から検索で
⾶んでくるとよし
Time range を⾒ないと、実は半年前に撲滅されたクエリー
を⼀⽣懸命EXPLAINする⽻目に遭ったり
単発のクエリーが⼤きくて累...
ダイジェストごと、後半
# Query_time distribution
# 1us
# 10us
# 100us
# 1ms
# 10ms
# 100ms
# 1s
# 10s+ ##############################...
ダイジェストごと、後半
クエリーごとにバラつきがあるか︖
バラついているなら、カーディナリティーの悪戯か、それともキャッ
シュの具合か
特にInnoDB圧縮を使ってる場合、バッファプールミスヒットやテーブルキャッシュミ
スヒットのコストは⼤きい...
pt-query-digestと上⼿く付き合うコツ
--since オプションはほぼ必須
--since オプションでもログは舐めてしまうので、⼤きなログを⾷わ
すのであれば tail -50000 slow.log | pt-query-di...
with Anemometer
pt-query-digest の出⼒結果を可視化するツール
pt-query-digest の結果をMySQLに⼊れる機能(--history,
--review)をそのまま使ってる
box/Anemomete...
Anemometerの弱点
テーブル上UNIQUE KEY (hostname_max, checksum, ts_min,
ts_max)で、Anemometerはts_minでプロットするため、そ
のクエリーがts_minに集中したことにな...
Anemometerの弱点
⽇次で pt-query-digest を回している程度だと、⽇単位までし
か分解できない
16/79
anemo eat er
スローログをスプリットして pt-query-digest を呼びまくる
1分ぶんずつ pt-query-digest に⾷わせれば、ts_min と ts_max の差
は最⼤でも1分
-
AnemometerをDo...
with anemo eat er
1分単位でプロットできる
18/79
anemo eat er
リアルタイムでなくてもいい
スロークエリーのリアルタイム通知は別の⽅法でしてる-
グラフで⾒られれば数分前の情報であっても全然構わない-
リアルタイムを捨てて
保存期間を考えない
スローログが残っている限りの情報を、最...
anemo eat er
現在のところ docker と pt-query-digest はホストにインス
トールしておかないとダメ
$ git clone https://github.com/yoku0825/anemoeater
$ cd...
pt-query-digest
だいたいこんな感じでDailyの動きをメールで⾶ばしてる
気になったら anemo eat erで⾒る
$ pt-query-digest --since=$(date -d yesterday "+%Y-%m-...
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, ...
実はこれ、5.6
と5.7で実⾏計
画が違う
26/79
5.6
*************************** 1. row ***************************
id: 1
select_type: PRIMARY
table: <derived2>
type: ref
...
5.7
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: C
partitions: NULL
typ...
5.6
mysql> SHOW WARNINGSG
*************************** 1. row ***************************
Level: Note
Code: 1003
Message: /...
5.7
> SHOW WARNINGSG
*************************** 1. row ***************************
Level: Note
Code: 1003
Message: /* sel...
EXPLAIN EXTENDED
5.7からはデフォルトでEXTENDEDがついてくる
EXPLAIN直後に SHOW WARNINGS でオプティマイザーが最適化した後
のクエリーが⾒える
-
想像したのと違う遅くなり⽅ をしたらEXTEND...
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で、頑...
Data Input Methodのデフォルトを⼀気にSQLで書き換
えるとか
mysql> UPDATE data_input_fields JOIN data_input_data ON data_input_fields.id
= dat...
Device追加する時にポートを⼀⻫に変えるブックマーク
レットだとか
javascript:void((function(elems,port){for(var p in elems){elems[p
].value=port}})(docu...
みんなどうし
てるんだろう
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 Loc...
innotop
41/79
innotop
地味に機能は多いけど今のバージョンだと表⽰されない項目
がたまにある
旧バージョンのサポート切れば楽なんだけど…と思ったり思わなかっ
たり
-
ALTER TABLE や percona-toolkit で重いことやる時のおとも...
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...
SHOW PROFILE
mysql> SET @@profiling= 1;
Query OK, 0 rows affected, 1 warning (0.01 sec)
mysql> ..;
mysql> SHOW PROFILE;
+-...
SHOW PROFILE
組み込みだから使うのは超簡単
プロファイルを「どう解析するか」はまた別の問題
ざっと⾒てわかりやすいところに時間がかかってたらつぶせ
る…くらいのノリ
再現性がないとつらい
47/79
SHOW PROFILE S
mysql> SHOW PROFILES;
+----------+-------------+-----------------------------------------------------------...
SHOW PROFILE FOR QUERY ..
mysql> SHOW PROFILE FOR QUERY 4;
+------------------------------+-----------+
| Status | Duratio...
SHOW PROFILE
MySQL 5.6でdeprecated
代替として performance_schema.events_stages_* と
events_statements_* が案内されている…けど
-
@@profiling...
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になってる-
計測する項目も「だいたい必要になりそうなところ」だけ...
p_s.setup_*
mysql> SHOW TABLES FROM performance_schema LIKE 'setup_%';
+-----------------------------------------+
| Table...
p_s.setup_consumers
mysql> SELECT * FROM setup_consumers;
+----------------------------------+---------+
| NAME | ENABLED ...
p_s.setup_instruments
mysql> SELECT SUBSTRING_INDEX(`name`, '/', 2) AS short_name, ANY_VALUE(name) AS example, SUM(ENABLED...
統計情報へのアクセス
mysql> SHOW TABLES;
..
| events_stages_summary_by_account_by_event_name |
| events_stages_summary_by_host_by_ev...
p̲s⾃体のモニタリング
mysql> SHOW ENGINE PERFORMANCE_SCHEMA STATUS;
+--------------------+-----------------------------------------...
sys
p̲sの情報を⾒やすくするためのビューやストアドファンク
ション、ストアドプロシージャ
名前空間として sys スキーマを使うのでそう呼ぶことも
performance_schema = OFF の状態ではほとんどからっぽ
MySQL ...
sysのインストール(5.6向け)
$ git clone https://github.com/mysql/mysql-sys.git
Initialized empty Git repository in /root/mysql-sys/....
sys.statement_analysis
p_s.events_statements_summary_by_digest のビュー
超⾒やすい
これのためだけに p̲s有効にする価値がある
60/79
sys.statement_analysis
mysql> SELECT * FROM statement_analysisG
..
*************************** 2. row ********************...
sys.innodb_lock_waits
いわゆるSH2さんの アレ とほぼ同等の機能
これは i̲s のビューなので、p̲sが無効でもフツーに⾒られ
る
バンドルされて便利になったという感じ
62/79
sys.innodb_lock_waits
mysql57> SELECT * FROM innodb_lock_waitsG
*************************** 1. row ***********************...
sys.ps_truncate_all_tables
ストアド
p̲s は起動時から統計情報を累積するが、それをリセットす
るにはp̲sの各テーブルに対してTRUNCATEが必要
それを全部まとめてやってくれる、ただそれだけなんだけど
便利なス...
sys.x$*
x$ で始まるビューは、 x$ のない他のビューと対になってい
る
フツーの⽅は、[kMG]B をまとめたり [num]s をまとめた
りしてくれるが、そうすると⽂字列になっちゃうのでソート
に不便
そんな時、 x$ のビューは...
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 Calen...
Questions
and/or
Suggestions?
79/79
Próxima SlideShare
Cargando en…5
×

MySQLerの7つ道具

5.025 visualizaciones

Publicado el

2016/11/26 中国地方DB勉強会 in 広島

Publicado en: Tecnología
  • Follow the link, new dating source: ❤❤❤ http://bit.ly/2F7hN3u ❤❤❤
       Responder 
    ¿Estás seguro?    No
    Tu mensaje aparecerá aquí
  • Dating for everyone is here: ❤❤❤ http://bit.ly/2F7hN3u ❤❤❤
       Responder 
    ¿Estás seguro?    No
    Tu mensaje aparecerá aquí

MySQLerの7つ道具

  1. 1. MySQLerの七つ道具 2016/11/26 yoku0825 第18回 中国地⽅DB勉強会 in 広島
  2. 2. \こんにちは/ yoku0825@GMOメディア株式会社 オラクれない- ポスグれない- マイエスキューエる- ⽣息域 Twitter: @yoku0825- Blog: ⽇々の覚書- MyNA ML: ⽇本MySQLユーザ会- MySQL Casualʼs Slack: MySQL Casual- 1/79
  3. 3. MySQLer七つ道具 pt-query-digest1. EXPLAIN2. PMP for Cacti3. innotop4. SHOW PROFILE5. performance̲schema & sys6. ???7. 2/79
  4. 4. MySQLer七つ道具 pt-query-digest1. EXPLAIN2. PMP for Cacti3. innotop4. SHOW PROFILE5. performance̲schema & sys6. ???7. 3/79
  5. 5. pt-query-digest みんなだいすきPercona Toolkitの⼈気No.1 スローログをまとめて⾒やすくしてくれる ⼤⽂字⼩⽂字、⽂字列定数と数値定数をノーマライズして「ダイジェ スト」ごとに集約 - 4/79
  6. 6. 先頭のセクション $ 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
  7. 7. 先頭のセクション まああんま⾒ない 6/79
  8. 8. ダイジェスト⼀覧 # 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
  9. 9. ダイジェスト⼀覧 デフォルトでは「トータルでかかった時間」の降順 --order-by で変えられるデフォルトは “Query̲time:sum” 書き⽅にちょっとクセがある Query̲time:max Query̲time:sum Rows̲examined:max bytes:sum とか - 8/79
  10. 10. ダイジェストごと、前半 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
  11. 11. ダイジェストごと、前半 1⾏目に ID 0x.. があるので、ダイジェスト⼀覧から検索で ⾶んでくるとよし Time range を⾒ないと、実は半年前に撲滅されたクエリー を⼀⽣懸命EXPLAINする⽻目に遭ったり 単発のクエリーが⼤きくて累計 Exec time が⼤きくなってる のか、満遍なく出続けているのか anemo eat erも便利だよ- Rows examine / Rows_sent GROUP BYを除くと、⽐率が1に近く低いほど理想- Lock time はInnoDBではアテにならないので注意 10/79
  12. 12. ダイジェストごと、後半 # Query_time distribution # 1us # 10us # 100us # 1ms # 10ms # 100ms # 1s # 10s+ ######################################################## ######## # Tables .. # EXPLAIN /*!50100 PARTITIONS*/ SELECT .. 11/79
  13. 13. ダイジェストごと、後半 クエリーごとにバラつきがあるか︖ バラついているなら、カーディナリティーの悪戯か、それともキャッ シュの具合か 特にInnoDB圧縮を使ってる場合、バッファプールミスヒットやテーブルキャッシュミ スヒットのコストは⼤きい - 均等に遅いなら、それはクソクエリーかな- ただし pt-query-digest がそもそも、スローログに載っているヤーツ しか⾒られない以上、まともな速度で応答を返しているヤーツは検出 されない - 最後の⾏はEXPLAIN⽤に1⾏、集約してないやつを引っこ抜 いてくれるだけ オプションによっては⾃動でEXPLAINまでかけてくれる- 12/79
  14. 14. 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
  15. 15. with Anemometer pt-query-digest の出⼒結果を可視化するツール pt-query-digest の結果をMySQLに⼊れる機能(--history, --review)をそのまま使ってる box/Anemometer: Box SQL Slow Query Monitor 14/79
  16. 16. 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
  17. 17. Anemometerの弱点 ⽇次で pt-query-digest を回している程度だと、⽇単位までし か分解できない 16/79
  18. 18. anemo eat er スローログをスプリットして pt-query-digest を呼びまくる 1分ぶんずつ pt-query-digest に⾷わせれば、ts_min と ts_max の差 は最⼤でも1分 - AnemometerをDockerコンテナーとして起動する- 既存のAnemometerがあれば単にスローログを分割して⾷わせる pt- query-digest のラッパーとして呼べる - 17/79
  19. 19. with anemo eat er 1分単位でプロットできる 18/79
  20. 20. anemo eat er リアルタイムでなくてもいい スロークエリーのリアルタイム通知は別の⽅法でしてる- グラフで⾒られれば数分前の情報であっても全然構わない- リアルタイムを捨てて 保存期間を考えない スローログが残っている限りの情報を、最初から、最後まで⾒られる - ⾒るかどうかもわからないグラフのために常時リソースを割かなくて いい ⾒たく / ⾒せたく なったら起動、⾒終わったら停⽌ - 19/79
  21. 21. 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
  22. 22. 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
  23. 23. MySQLer七つ道具 pt-query-digest1. EXPLAIN2. PMP for Cacti3. innotop4. SHOW PROFILE5. performance̲schema & sys6. ???7. 22/79
  24. 24. EXPLAIN 今更なのでEXTENDEDの話しかしないよ 23/79
  25. 25. 目XPLAIN 出来る⼈︖ 24/79
  26. 26. 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
  27. 27. 実はこれ、5.6 と5.7で実⾏計 画が違う 26/79
  28. 28. 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
  29. 29. 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
  30. 30. 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
  31. 31. 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
  32. 32. EXPLAIN EXTENDED 5.7からはデフォルトでEXTENDEDがついてくる EXPLAIN直後に SHOW WARNINGS でオプティマイザーが最適化した後 のクエリーが⾒える - 想像したのと違う遅くなり⽅ をしたらEXTENDED⾒た⽅が 良い 特に5.6の蝉ジョインとか蝉ジョインとか蝉ジョインとか- MySQL :: MySQL 5.6 リファレンスマニュアル :: 8.8.3 EXPLAIN EXTENDED 出⼒フォーマット 31/79
  33. 33. MySQLer七つ道具 pt-query-digest1. EXPLAIN2. PMP for Cacti3. innotop4. SHOW PROFILE5. performance̲schema & sys6. ???7. 32/79
  34. 34. PMP(Percona Monitoring Plugins) for Cacti 別に for Zabbixでもいいと思う 単にウチはもともとCactiを使っていたからというだけ 33/79
  35. 35. PMP for Cacti rrdtoolだから容量効率は素晴らしい rrdtoolだから丸め誤差は厳しい CactiそのものがWEBからポチポチするインターフェースな のつらい ss̲get̲mysql̲stats.php ⾃体はPHPで、頑張って⾊々パー スしてるので、ホゲろうと思えばホゲれる けど、それならPerlで書きたい- 34/79
  36. 36. 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
  37. 37. 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
  38. 38. みんなどうし てるんだろう 37/79
  39. 39. PMP for Cacti やっぱり視認性だいじ 絶対値に惑わされない 問題が起きていなくてもたまには⾒る たまには⻑い期間で⾒る 使いづらいものはユーティリティー作っちゃえばいいと思う 38/79
  40. 40. MySQLer七つ道具 pt-query-digest1. EXPLAIN2. PMP for Cacti3. innotop4. SHOW PROFILE5. performance̲schema & sys6. ???7. 39/79
  41. 41. innotop みんな⼤好き、topライクに SHOW PROCESSLIST を表⽰して くれるinnotop 地味に “M” (Replication Status) も便利 なんとMSR対応してるんだぜ - “L” (InnoDB Locks) とか- “T” (InnoDB Transaction) とか- pt-osc してる間だと “D” (InnoDB Deadlocks) を眺めることもある- tmuxでばっちんばっちんターミナル割って、 dstat とか流 しながら⾒るのが好き 40/79
  42. 42. innotop 41/79
  43. 43. innotop 地味に機能は多いけど今のバージョンだと表⽰されない項目 がたまにある 旧バージョンのサポート切れば楽なんだけど…と思ったり思わなかっ たり - ALTER TABLE や percona-toolkit で重いことやる時のおとも に最適 “d” で表⽰間隔の変更。0.1とかやるとたのしい- ただし万能感を期待しない- “Q” => “K” => “T” => “k” (killステートメント) のコンボで詰まっ てるのを殺すくらい - 42/79
  44. 44. innotop 中⾝は結構スパゲティ 最近メンテナンス遅め ちょっと⾊々事情が- ⽇々の覚書: innotopのその後 2016年6⽉- 43/79
  45. 45. MySQLer七つ道具 pt-query-digest1. EXPLAIN2. PMP for Cacti3. innotop4. SHOW PROFILE5. performance̲schema & sys6. ???7. 44/79
  46. 46. SHOW PROFILE MySQLの組み込みプロファイラー 「そのクエリーが実⾏されていた期間、どのStatus(SHOW PROCESSLIST で “State” と表⽰されているもの)にどのくら いの時間かかったか 使うのが超簡単 45/79
  47. 47. 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
  48. 48. SHOW PROFILE 組み込みだから使うのは超簡単 プロファイルを「どう解析するか」はまた別の問題 ざっと⾒てわかりやすいところに時間がかかってたらつぶせ る…くらいのノリ 再現性がないとつらい 47/79
  49. 49. 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
  50. 50. 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
  51. 51. SHOW PROFILE MySQL 5.6でdeprecated 代替として performance_schema.events_stages_* と events_statements_* が案内されている…けど - @@profiling はセッション単位に対して、p̲sはセッション単位の調 整がちょっと難しい - ⼀応、MySQL 8.0.0現在でもまだ使える 50/79
  52. 52. MySQLer七つ道具 pt-query-digest1. EXPLAIN2. PMP for Cacti3. innotop4. SHOW PROFILE5. performance̲schema & sys6. ???7. 51/79
  53. 53. performance̲schema(p̲s) パフォーマンスモニタリング専⽤のストレージエンジン MySQL 5.6から真っ当に使えるようになってる 吊るしのデフォルトではONになってる- 計測する項目も「だいたい必要になりそうなところ」だけがONになっ てるので、必要になるまではそのまま使えばOK - メモリーを⾷うのは相変わらず デフォルトがautosizeなので、気になる場合は固定値を決め打つ- しかも5.7のデフォルトが auto re size になりやがった。。- 52/79
  54. 54. 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
  55. 55. 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
  56. 56. 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
  57. 57. 統計情報へのアクセス 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
  58. 58. 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
  59. 59. sys p̲sの情報を⾒やすくするためのビューやストアドファンク ション、ストアドプロシージャ 名前空間として sys スキーマを使うのでそう呼ぶことも performance_schema = OFF の状態ではほとんどからっぽ MySQL 5.7では最初から導⼊済み MySQL 5.6にも対応 GitHubのmysql-sysリポジトリー からインストール- 58/79
  60. 60. 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
  61. 61. sys.statement_analysis p_s.events_statements_summary_by_digest のビュー 超⾒やすい これのためだけに p̲s有効にする価値がある 60/79
  62. 62. 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
  63. 63. sys.innodb_lock_waits いわゆるSH2さんの アレ とほぼ同等の機能 これは i̲s のビューなので、p̲sが無効でもフツーに⾒られ る バンドルされて便利になったという感じ 62/79
  64. 64. 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
  65. 65. 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
  66. 66. sys.x$* x$ で始まるビューは、 x$ のない他のビューと対になってい る フツーの⽅は、[kMG]B をまとめたり [num]s をまとめた りしてくれるが、そうすると⽂字列になっちゃうのでソート に不便 そんな時、 x$ のビューは何の整形もしないので…ってこと だと思う でもナノ秒単位とか正直つらいので、ソートだけ x$ でやって digest カラムとかでフツーのビューとJOINした⽅がいいと思う - 65/79
  67. 67. MySQLer七つ道具 pt-query-digest1. EXPLAIN2. PMP for Cacti3. innotop4. SHOW PROFILE5. performance̲schema & sys6. ???7. 66/79
  68. 68. Do you know “Dimitri”? 67/79
  69. 69. Dimitri KRAVTCHUK 68/79
  70. 70. Dimitriおじさん says 69/79
  71. 71. Dimitriおじさん says 70/79
  72. 72. Dimitriおじさん says 71/79
  73. 73. エコシステム たとえば MariaDB, Percona Server たとえば MHA for MySQL, HandlerSocket たとえば ⽇本MySQLユーザ会, MySQL Casual たとえば Oracle 72/79
  74. 74. USE YOUR BRAIN 73/79
  75. 75. but/and 74/79
  76. 76. YOU are not alone. 75/79
  77. 77. 2年前 76/79
  78. 78. みなさんのご参加をお待ちしております :) MyNA ML: ⽇本MySQLユーザ会 MySQL Casualʼs Slack: MySQL Casual 77/79
  79. 79. Advent Calendarのおさそい まだまだお席に余裕がございます 具体的には 20 名様ほどお⼊りいただけます- @soudai1025- @kkkida̲twtr- @kamipo- MySQL Casual Advent Calendar 2016 - Qiita 78/79
  80. 80. Questions and/or Suggestions? 79/79

×