SlideShare une entreprise Scribd logo
1  sur  65
Télécharger pour lire hors ligne
ヤフー社内でやってる
MySQLチューニングセミナー
大公開
2016/02/20 MyNA , JPUG 合同勉強会
ヤフーはどんなRDB使ってるの?
2
Yahoo! JAPANのRDB環境
• 11g RAC Enterprise Edition
• 約200DB
• サーバ 200台, Exadata もあるよ
• MySQL 5.1 (RR,Mixed)
Percona 5.5 (RR,Mixed)
Percona 5.6 (RC,RBR,GTID)
• 約500DB
• サーバ 300台
Oracle
Database
MySQL
Percona
4
自己紹介
Copyright (C) 2016 Yahoo Japan Corporation. All Rights Reserved. 無断引用・転載禁止
5
• 三谷 智史(@mita2)
• 所属 DBMS技術
RDB専門部隊 13名
• DB Administration 黒帯
DBAあるある
• へんなクエリ流されて、負荷が爆発
• SQLがスパゲッティすぎて解読不能
Copyright (C) 2016 Yahoo Japan Corporation. All Rights Reserved. 無断引用・転載禁止
6
RDBを正しく使ってもらうために、
社内でセミナーを実施しています。
ヤフー社内でやってる
MySQLチューニングセミナー大公開
Copyright (C) 2016 Yahoo Japan Corporation. All Rights Reserved. 無断引用・転載禁止
7
ご注意
• 個人の経験をもとに記載しています。間違った情報が含ま
れてたりするかもしれません。
• Version 5.5 を前提に記載しております。最新のバージョ
ンでは改善されているケースもあります。
Copyright (C) 2016 Yahoo Japan Corporation. All Rights Reserved. 無断引用・転載禁止
8
本日の流れ
1. インデックスについて
2. SQLチューニング手順
1. 重いクエリの洗い出し
2. 実行計画の確認
3. SQLチューニング例
※ InnoDBを前提。MyISAMはもう卒業しましょう。
Copyright (C) 2016 Yahoo Japan Corporation. All Rights Reserved. 無断引用・転載禁止
インデックスについて
• インデックスはツリー構造
• データはソートされている
• リーフノードに値と行のPKを格納
なぜ、インデックスで高速化するのか?
PK col1 time
1 a 11:15
2 f 01:10
3 d 03:01
: : :
SELECT * FROM t WHERE col1 = ‘f’
インデックス対象
a-p r-z
a
pk=1
d
pk=3
f
pk=2
p
pk=9
r
pk=4
t
pk=5
カーディナリティ
mysql> show index from t;
+-----+----------+----------+------------+-<SNIP>-+-----------+-------------+
|Table|Non_unique| Key_name |Seq_in_index| | Collation | Cardinality |
+-----+----------+----------+------------+--------+-----------+-------------+
| t | 0| PRIMARY | 1| | A | 5 |
+-----+----------+----------+------------+--------+-----------+-------------+
1 row in set (0.00 sec)
インデックス内のユニークな値
の多さを表した指数
Copyright (C) 2016 Yahoo Japan Corporation. All Rights Reserved. 無断引用・転載禁止
カーディナリティとは
• カーディナリティが低いと効果が少ない
• カーディナリティが高いデータの例
• AUTO_INCREMENT、住所、更新日時
• カーディナリティが低いデータの例
• フラグ、カテゴリ、都道府県
Copyright (C) 2016 Yahoo Japan Corporation. All Rights Reserved. 無断引用・転載禁止
なぜ効果が少ないのか?
0
pk=1
pk=3
pk=5
:
:
:
1
pk=2
pk=4
pk=6
:
:
:
PK is_pk_even_num
(PKが偶数か?)
time
1 0 11:15
2 1 12:31
3 0 13:44
4 1 14:01
: : :
1000000 1 20:01
SELECT * FROM t WHERE is_pk_even_num = 1
AND time <= 12:00
• 半分までしか絞り込めない
• インデックスを経由することによる
オーバーヘッドが無視できない
インデックス対象
×
50万回
PK is_pk_1000multi
(PKが1000の倍数?)
time
1 0 11:15
: 0 12:31
1000 1 13:44
: : 14:01
: : :
1000000 1 20:01
例外
0
pk=1
pk=2
pk=3
:
:
:
1
pk=1000
pk=2000
pk=3000
:
SELECT * FROM t WHERE is_pk_1000multi = 1
AND time <= 12:00
• 分布が偏っていれば効果が大きくなる
• 条件によって効果が異なる
インデックス対象
×
1000回
Copyright (C) 2016 Yahoo Japan Corporation. All Rights Reserved. 無断引用・転載禁止
Left-Most-Index
以下のインデックスは同じ?
違います
インデックスA.
CREATE INDEX idxA1 ON mytable (col1);
CREATE INDEX idxA2 ON mytable (col2);
インデックスB.
CREATE INDEX idxB1 ON mytable (col1, col2);
インデックスC.
CREATE INDEX idxC1 ON mytable (col2, col1);
Copyright (C) 2016 Yahoo Japan Corporation. All Rights Reserved. 無断引用・転載禁止
複合インデックスでは指定順が重要
a
pk=1
9 a
pk=2
8 b
pk=3
7 b
pk=4
6
5
pk=1
c 6
pk=4
b 7
pk=2
b 8
pk=3
a
インデックスB.
CREATE INDEX idxB1 ON mytable (col1, col2);
インデックスC.
CREATE INDEX idxC1 ON mytable (col2, col1);
a b~c
5~6 7~9
col2col1
col1col2
c
pk=5
5
9
pk=5
a
複合インデックスでは指定順が重要
絞り込み対象カラム
→
1.WHRER col1 =
‘x’
2.WHERE col2 =
‘x’
3.WHERE col1 = ‘x’ AND col2 = ‘x’
インデックスA idxA1
が利用される
idxA2
が利用される
idxA1, idxA2 どちらかが利用される。
※
インデックスB idxB1
が利用される
インデックスは利
用されない
idxB1 が利用される。
idxA1, idxA2より高速。
インデックスC インデックスは利
用されない
idxC1
が利用される
idxC1が利用される。
idxA1, idxA2より高速。
※ 場合によってはインデックスマージ
インデックスA.
CREATE INDEX idxA1 ON mytable (col1);
CREATE INDEX idxA2 ON mytable (col2);
インデックスB.
CREATE INDEX idxB1 ON mytable (col1, col2);
インデックスC.
CREATE INDEX idxC1 ON mytable (col2, col1);
インデックスを貼るときのポイント
• カーディナリティの高いカラムを選ぶ
• 複合インデックスのカラムの順に注意
• 更新性能・キャッシュ効率が低下するため、
必要なものだけに貼る
Copyright (C) 2016 Yahoo Japan Corporation. All Rights Reserved. 無断引用・転載禁止
SQLチューニング手順
SQLチューニングの手順
1. 重いクエリランキングを出す
2. 実行計画を確認する
3. チューニング
1. SQLの書き換え
2. インデックスを貼る
3. テーブル構成をみなおす etc
Copyright (C) 2016 Yahoo Japan Corporation. All Rights Reserved. 無断引用・転載禁止
SQLチューニングの手順
1. 重いクエリランキングを出す
2. 実行計画を確認する
3. チューニング
1. SQLの書き換え
2. インデックスを貼る
3. テーブル構成をみなおす etc
Copyright (C) 2016 Yahoo Japan Corporation. All Rights Reserved. 無断引用・転載禁止
重いSQLの洗い出し方 STEP1
スロークエリーログに全SQLを記録
$ sudo rm mysqld-slow.log
$ mysql –u user_name –p
mysql> SET GLOBAL long_query_time = 0;
mysql> SET GLOBAL log_slow_verbosity=full;
mysql> FLUSH LOGS;
# User@Host: user[user] @ [1.2.3.4]
# Query_time: 0.067361 Lock_time: 0.000030 Rows_sent: 16 Rows_examined: 121031
SET timestamp=1346772142;
SELECT zpam.zip_cd
FROM zip_area_mast zpam
WHERE zpam.point_cd = 11276 AND zpam.del_flag = 0;
:
実行時間
テーブルロックした時間
行ロックした時間はカウン
トされていので注意!
結果の行数
スキャンした行数
• Percona Tookit の pt-query-digest で集計
重いSQLの洗い出し方 STEP2
$ sudo pt-query-digest --group-by fingerprint¥
--order-by Query_time:sum ¥
--since '2015-06-14 00:00:00' --until '2015-06-14 23:59:59' ¥
mysqld-slow.log
合計実行時間でソート
オプション ソート条件
Query_time:avg 平均実行時間
Query_time:sum 合計実行時間
InnoDB_IO_r_bytes:sum バッファプールにヒットせず、DISKから読み取った
データ量
Copyright (C) 2016 Yahoo Japan Corporation. All Rights Reserved. 無断引用・転載禁止
集計結果
# Query 5: 39.92 QPS, 229.19kx concurrency, ID 0x72BFE142E32896BD at byte 88442
# Time range: 2015-10-29 23:00:00 to 23:59:59
# Attribute pct total min max avg 95% stddev median
# ============ === ======= ======= ======= ======= ======= ======= =======
# Count 31 143676
# Exec time 11 660s 150us 623ms 5ms 18ms 10ms 490us
# Lock time 20 13s 32us 5ms 91us 113us 30us 89us
# Rows sent 0 264.02k 0 4 1.88 2.90 0.69 1.96
# Rows examine 0 264.02k 0 4 1.88 2.90 0.69 1.96
# Rows affecte 0 0 0 0 0 0 0 0
# Rows read 0 264.02k 0 4 1.88 2.90 0.69 1.96
# Bytes sent 0 16.80M 83 171 122.61 143.84 17.33 124.25
# Merge passes 0 0 0 0 0 0 0 0
# Tmp tables 0 0 0 0 0 0 0 0
# Tmp disk tbl 0 0 0 0 0 0 0 0
# Tmp tbl size 0 0 0 0 0 0 0 0
# Query size 18 26.14M 148 271 190.81 246.02 51.01 143.84
# InnoDB:
# IO r bytes 9 786.66M 0 80.00k 5.61k 15.96k 9.17k 0
# IO r ops 9 49.17k 0 5 0.35 0.99 0.57 0
# IO r wait 14 569s 0 620ms 4ms 17ms 10ms 0
<省略>
SELECT topic_id FROM weather WHERE (consumeruri = ‘abc') AND (consumeruri_type = 'android')¥G
合計実行回数 平均実行時間
(1クエリあたり)
レスポンス行数(1クエリあたり)
クエリ
処理過程で読み込んだ行数
(1クエリあたり)
キャッシュヒットせずに
DISKから読んだバイト数
SQLチューニングの手順
1. 重いクエリランキングを出す
2. 実行計画を確認する
3. チューニング
1. SQLの書き換え
2. インデックスを貼る
3. テーブル構成をみなおす etc
Copyright (C) 2016 Yahoo Japan Corporation. All Rights Reserved. 無断引用・転載禁止
実行計画の確認
• 実行計画=クエリの処理の流れ
• 「EXPLAIN」をクエリの先頭に付ける
• 更新系クエリはSELECTに書き換え
UPDATE t SET col = newvalue WHERE condition = ‘x’;
EXPLAIN SELECT col FROM t WHERE condition = ‘x’;
Copyright (C) 2016 Yahoo Japan Corporation. All Rights Reserved. 無断引用・転載禁止
EXPLAINの結果の例
mysql> EXPLAIN SELECT t1.pk, t1.col1, t2.col2
FROM t1 INNER JOIN t2
ON (t1.pk = t2.fk)
WHERE t1.pk = 1;
+----+------------+------+------+--------------------+--------+--------+------+-----+-------------+
| id | select_type| table| type | possible_keys | key | key_len| ref | rows| Extra |
+----+------------+------+------+--------------------+--------+--------+------+-----+-------------+
| 1 | SIMPLE | t1 | const| PRIMARY,pk_col1_idx| PRIMARY| 4 | const| 1| |
| 1 | SIMPLE | t2 | ALL | NULL | NULL | NULL | NULL | 5| Using where |
+----+------------+------+------+--------------------+--------+--------+------+-----+-------------+
カラム 説明
id SELECTごとに振られるID。処理順ではない点に注意。
select_type SELECTの種類。SIMPLE, SUBQUERY, UNIONなど。
type テーブルへのアクセス方法。インデックスの利用有無、読取範囲などがわかる。
possible_keys 利用可能なインデックス。
key 実際に利用されたインデックス。possible_keys からインデックスの内容や統計情報を加味して、選択さ
れたインデックス。
key_len 読み取ったインデックスのバイト数。
ref 比較するカラム。constの場合は定数(WHERE x = 1のような場合)。
rows スキャンする見積もり行数。JOINやサブクエリが関係する場合は外部表のrows × 内部表のrowsがス
キャンする行になる。
Extra その他の情報
SQLチューニングの手順
1. 重いクエリランキングを出す
2. 実行計画を確認する
3. チューニング
1. SQLの書き換え
2. インデックスを貼る
3. テーブル構成をみなおす etc
Copyright (C) 2016 Yahoo Japan Corporation. All Rights Reserved. 無断引用・転載禁止
チューニング例
代表的なチューニング例
1. type=ALL または type=index で rows が大きい
2. Extra に Using temporary; Using filesort でrowsが大きい
3. select_type が DEPENDENT SUBQUERY
4. JOINにおいて2つ目以降のExtraにUsing whereが出力さてい
て rows が大きい
5. 大量更新
6. データ削除
Copyright (C) 2016 Yahoo Japan Corporation. All Rights Reserved. 無断引用・転載禁止
代表的なチューニング例
1. type=ALL または type=index で rows が大きい
2. Extra に Using temporary; Using filesort でrowsが大きい
3. select_type が DEPENDENT SUBQUERY
4. JOINにおいて2つ目以降のExtraにUsing whereが出力さてい
て rows が大きい
5. 大量更新
6. データ削除
Copyright (C) 2016 Yahoo Japan Corporation. All Rights Reserved. 無断引用・転載禁止
【1.フルスキャン】 TYPE=ALL
mysql> EXPLAIN SELECT push_id FROM push_info
WHERE deleted=1 AND datediff(now(), mod_date) > '180';
+--+-----------+---------+----+-------------+----+-------+----+-------+--------------------------+
|id|select_type|table |type|possible_keys|key |key_len|ref |rows |Extra |
+--+-----------+---------+----+-------------+----+-------+----+-------+--------------------------+
|1 |SIMPLE |push_info|ALL |NULL |NULL|NULL |NULL|1115182|Using where; |
+--+-----------+---------+----+-------------+----+-------+----+-------+--------------------------+
mysql> SHOW INDEX FROM push_info;
+-----------+------------+--------------------+--+----------+--------+------+------------+
| Table | Non_unique | Key_name |~| Sub_part | Packed | Null | Index_type |
+-----------+------------+--------------------+--+----------+--------+------+------------+
| push_info | 0 | PRIMARY |~| NULL | NULL | | BTREE |
+-----------+------------+--------------------+--+----------+--------+------+------------+
• mod_dateとdeletedにインデックスを貼るべき
• 関数を適用した場合インデックスは効かない
• すべての行に対してdatediffを実行してるのも×
• mod_date < date_sub(NOW(), INTERVAL 180 DAY) と書くべき
全部読み込み 行数多い
111万行に対し
て絞り込み
インデックスが効かない条件
Extra
関数 WHERE datediff(now(), mod_date) > '180'
式 WHERE col1 / 2 = 0
否定構文 WHERE col1 != 3
LIKE検索
※ 前方一致除く
WHERE col1 LIKE ‘%string%’
WHERE col1 LIKE ‘%string’
Copyright (C) 2016 Yahoo Japan Corporation. All Rights Reserved. 無断引用・転載禁止
【1.フルスキャン】チューニング結果
mysql> CREATE INDEX idx01 ON push_info(deleted, mod_date);
mysql> EXPLAIN SELECT push_id FROM push_info
WHERE deleted=1 AND mod_date < date_sub(NOW(), INTERVAL 180 DAY);
+----+-------------+-----------+-------+-------+------+------+--------------------------+
| id | select_type | table | type | key | ref | rows | Extra |
+----+-------------+-----------+-------+-------+------+------+--------------------------+
| 1 | SIMPLE | push_info | range | idx01 | NULL | 10 | Using index |
+----+-------------+-----------+-------+-------+------+------+--------------------------+
インデックスの
範囲読み込み
行数が10行 インデックスだ
けで解決でき
るクエリ
• Before: 380msec → After: 0msec
Copyright (C) 2016 Yahoo Japan Corporation. All Rights Reserved. 無断引用・転載禁止
代表的なチューニング例
1. type=ALL または type=index で rows が大きい
2. Extra に Using temporary; Using filesort でrowsが大きい
3. select_type が DEPENDENT SUBQUERY
4. JOINにおいて2つ目以降のExtraにUsing whereが出力さていて
rows が大きい
5. 大量更新
6. データ削除
Copyright (C) 2016 Yahoo Japan Corporation. All Rights Reserved. 無断引用・転載禁止
【2.ソート】
mysql> EXPLAIN SELECT order_time,seller_id,image_id,item_id,<省略>
FROM order_master WHERE is_hidden_page = '0'
ORDER BY order_time DESC LIMIT 20;
+--+-----------+--------------+----+---------------+----+----------+-----------------------------+
|id|select_type| table |type| possible_keys |key | rows | Extra |
+--+-----------+--------------+----+---------------+----+----------+-----------------------------+
| 1|SIMPLE | order_master |ALL | NULL |NULL| 12200494 | Using where; Using filesort |
+--+-----------+--------------+----+---------------+----+----------+-----------------------------+
• is_hidden_page は殆どの行で0
• カーディナリティが低いため×
• ソートにインデックスは有効か?
• LIMIT句がある場合に効果が高い
1200万件
ソートしている
Copyright (C) 2016 Yahoo Japan Corporation. All Rights Reserved. 無断引用・転載禁止
【2.ソート】チューニング結果
mysql> CREATE INDEX OM_OTM ON order_master (order_time);
mysql> EXPLAIN SELECT order_time,seller_id,image_id,item_id,<省略>
FROM order_master WHERE is_hidden_page = '0'
ORDER BY order_time DESC LIMIT 20;
+--+-------------+--------------+-----+---------------+--------+------+-------------+
|id| select_type | table |type | possible_keys | key | rows | Extra |
+--+-------------+--------------+-----+---------------+--------+------+-------------+
| 1| SIMPLE | order_master |index| NULL | OM_OTM | 20 | Using where |
+--+-------------+--------------+-----+---------------+--------+------+-------------+
20個だけ取る
• インデックスはソート済みのため、ソートが不要
• 上位20件だけ取ったら、処理を終了
• Before: 4300sec → After: 0sec
ソートがなくなるインデックス利用
Copyright (C) 2016 Yahoo Japan Corporation. All Rights Reserved. 無断引用・転載禁止
【2.ソート】 CALC_FOUND_ROWSはNG
• SQL_CALC_FOUND_ROWS句
• 条件にマッチしたレコードが全部で何件あったかを返す
• LIMIT句と一緒に使う
• 「全部で何件」= LIMIT句がないのと同じ
Copyright (C) 2016 Yahoo Japan Corporation. All Rights Reserved. 無断引用・転載禁止
【2.ソート】 考慮事項
• 1度に使われるインデックスは、
各テーブルにつき1つ
• 選択が必要
• ソートを最適化する
• 絞り込み(WHERE句)を最適化する
Copyright (C) 2016 Yahoo Japan Corporation. All Rights Reserved. 無断引用・転載禁止
代表的なチューニング例
1. type=ALL または type=index で rows が大きい
2. Extra に Using temporary; Using filesort でrowsが大きい
3. select_type が DEPENDENT SUBQUERY
4. JOINにおいて2つ目以降のExtraにUsing whereが出力さていて
rows が大きい
5. 大量更新
6. データ削除
Copyright (C) 2016 Yahoo Japan Corporation. All Rights Reserved. 無断引用・転載禁止
【3.相関サブクエリ】
mysql> EXPLAIN SELECT team_name
FROM team
WHERE team_id IN (SELECT team_id FROM member WHERE skill IN ("C"));
+----+--------------------+--------+------+---------------+省略+------+-------------+
| id | select_type | table | type | possible_keys | | rows | Extra |
+----+--------------------+--------+------+---------------+----+------+-------------+
| 1 | PRIMARY | team | ALL | NULL | | 3 | Using where |
| 2 | DEPENDENT SUBQUERY | member | ALL | NULL | | 5 | Using where |
+----+--------------------+--------+------+---------------+----+------+-------------+
team_id team_name
1 Team1
2 Team2
3 Team3
team_id member_name skill
1 Yahoo Taro C
1 Yahoo Jiro Python
2 Yahoo Hanako Ruby
2 Yahoo Saburo PHP
3 Yahoo Sirou Perl
■ member■ team
Copyright (C) 2016 Yahoo Japan Corporation. All Rights Reserved. 無断引用・転載禁止
【3.相関サブクエリ】 期待する動作
team_id team_name
1 Team1
2 Team2
3 Team3
team_id member_name skill
1 Yahoo Taro C
1 Yahoo Jiro Python
2 Yahoo Hanako Ruby
2 Yahoo Saburo PHP
3 Yahoo Sirou Perl
mysql> EXPLAIN SELECT team_name
FROM team
WHERE team_id IN (SELECT team_id FROM member WHERE skill IN ("C"));
最初に実行される
ことを期待
①skill=Cを探す②team_id=1を探す
• memberテーブルを1回読み込む
• teamテーブルを1回読み込む
• 合計=5 + 3 = 8行の読み込みを期待する
【3.相関サブクエリ】 実際の動き
mysql> EXPLAIN SELECT team_name
FROM team
WHERE team_id IN (SELECT team_id FROM member WHERE skill IN ("C"));
team_id team_name
1 Team1
2 Team2
3 Team3
team_id member_name skill
1 Yahoo Taro C
1 Yahoo Jiro Python
2 Yahoo Hanako Ruby
2 Yahoo Saburo PHP
3 Yahoo Sirou Perl
team_id =1 AND skill=C
のレコードを探す
• 合計= 3 + 3 * 5 = 18行の読み込み
• 実行計画の「PRIMARY」は外部表(親)を示す
• なぜ、期待どうりに動かないのか?
• MySQLの仕様です。。。(5.6で改善されます)
【3.相関サブクエリ】 チューニング方法(1)
mysql> CREATE INDEX idx_skill ON member(skill, team_id);
mysql> EXPLAIN SELECT team_name
FROM team
WHERE team_id IN (SELECT team_id FROM member WHERE skill IN ("C"));
+----+--------------------+--------+------+---------------+-----------+省略+------+-------------+
| id | select_type | table | type | possible_keys | key | | rows | Extra |
+----+--------------------+--------+------+---------------+-----------+省略+------+-------------+
| 1 | PRIMARY | team | ALL | NULL | NULL | | 3 | Using where |
| 2 | DEPENDENT SUBQUERY | member | ref | idx_skill | idx_skill | | 1 | Using where |
+----+--------------------+--------+------+---------------+-----------+省略+------+-------------+
•サブクエリの実行にインデックスを利用
•3 + 3 * 1 = 6行に(見積もり)
+----+--------------------+--------+------+---------------+省略+------+-------------+
| id | select_type | table | type | possible_keys | | rows | Extra |
+----+--------------------+--------+------+---------------+----+------+-------------+
| 1 | PRIMARY | team | ALL | NULL | | 3 | Using where |
| 2 | DEPENDENT SUBQUERY | member | ALL | NULL | | 5 | Using where |
+----+--------------------+--------+------+---------------+----+------+-------------+
インデックス未使用
【3.相関サブクエリ】 チューニング方法(2)
mysql> EXPLAIN SELECT team_name
FROM team JOIN member USING(team_id)
WHERE member.skill IN ("C");
+----+-------------+--------+--------+---------------+-----------+---------------------+------+
| id | select_type | table | type | possible_keys | key | ref | rows |
+----+-------------+--------+--------+---------------+-----------+---------------------+------+
| 1 | SIMPLE | member | ref | idx_skill | idx_skill | const | 1 |
| 1 | SIMPLE | team | eq_ref | PRIMARY | PRIMARY | test.member.team_id | 1 |
+----+-------------+--------+--------+---------------+-----------+---------------------+------+
member表を先に読む
• JOINに書き換える
• 相関サブクエリ、だいたいJOINで書き直せる
• オプティマイザが親子を自動判断
• member表を外部表(駆動表)にする
+----+--------------------+--------+------+---------------+-----------+省略+------+-------------+
| id | select_type | table | type | possible_keys | key | | rows | Extra |
+----+--------------------+--------+------+---------------+-----------+省略+------+-------------+
| 1 | PRIMARY | team | ALL | NULL | NULL | | 3 | Using where |
| 2 | DEPENDENT SUBQUERY | member | ref | idx_skill | idx_skill | | 1 | Using where |
+----+--------------------+--------+------+---------------+-----------+省略+------+-------------+
代表的なチューニング例
1. type=ALL または type=index で rows が大きい
2. Extra に Using temporary; Using filesort でrowsが大きい
3. select_type が DEPENDENT SUBQUERY
4. JOINにおいて2つ目以降のExtraにUsing whereが出力さ
ていて rows が大きい
5. 大量更新
6. データ削除
Copyright (C) 2016 Yahoo Japan Corporation. All Rights Reserved. 無断引用・転載禁止
【4.JOIN】NL結合
• MySQLは「NestedLoop結合」のみをサポート
• どんな結合条件でも対応可
• 最速とは限らないがバランスの良いアルゴリズム
Copyright (C) 2016 Yahoo Japan Corporation. All Rights Reserved. 無断引用・転載禁止
【4.JOIN】NL結合
pref_id prefecture
1 Hokkaido
2 Aomori
3 Iwate
pref_id name age
1 Yamada 20
1 Takana 33
2 Yamamoto 12
2 Ogawa 76
3 Inoue 90
■ prefecture ■ people
■ cities - pref_id_idx
mysql> EXPLAIN SELECT prefecture
FROM prefecture INNER JOIN people USING(pref_id)
WHERE people.age >= 120;
+--+-----------+----------+----+-------------+-----------+--------------------+------+-----------+
|id|select_type|table |type|possible_keys|key | ref |rows |Extra |
+--+-----------+----------+----+-------------+-----------+--------------------+------+-----------+
| 1|SIMPLE |prefecture|ALL |pref_id |NULL | NULL | 47| |
| 1|SIMPLE |people |ref |pref_id_idx |pref_id_idx| prefecture.pref_id |173891|Using where|
+--+-----------+----------+----+-------------+-----------+--------------------+------+-----------+
上に表示される
表が外部表
pref_idカラムのインデックスを
利用して内部表からデータを取得
• NLはループの中にSELECTが入っているイメージ
:
:
:
:
【4.JOIN】NL結合
pref_id prefecture
1 Hokkaido
2 Aomori
3 Iwate
pref_id name age
1 Yamada 20
1 Takana 33
2 Yamamoto 12
2 Ogawa 76
3 Inoue 90
■ prefecture ■ people
■ cities - pref_id_idx
mysql> EXPLAIN SELECT prefecture
FROM prefecture INNER JOIN people USING(pref_id)
WHERE people.age >= 120;
+--+-----------+----------+----+-------------+-----------+--------------------+------+-----------+
|id|select_type|table |type|possible_keys|key | ref |rows |Extra |
+--+-----------+----------+----+-------------+-----------+--------------------+------+-----------+
| 1|SIMPLE |prefecture|ALL |pref_id |NULL | NULL | 47| |
| 1|SIMPLE |people |ref |pref_id_idx |pref_id_idx| prefecture.pref_id |173891|Using where|
+--+-----------+----------+----+-------------+-----------+--------------------+------+-----------+
ちょっと大きめ
:
:
:
x47
17万行から
age>=120を探す
47 x 17万行
スキャン
17万行
【4.JOIN】チューニング
• ループ回数を少なくする
• 結合条件以外の条件にマッチする件数を
テーブルごとにカウント
• 件数が少ないほうを外部表にする
mysql> SELECT COUNT(*) FROM prefecture;
+----------+
| COUNT(*) |
+----------+
| 47 |
+----------+
1 row in set (0.00 sec)
mysql> SELECT COUNT(*) FROM people where age >=120;
+----------+
| COUNT(*) |
+----------+
| 3 |
+----------+
1 row in set (0.70 sec)
mysql> EXPLAIN SELECT prefecture
FROM prefecture INNER JOIN people USING(pref_id)
WHERE people.age >= 120;
Copyright (C) 2016 Yahoo Japan Corporation. All Rights Reserved. 無断引用・転載禁止
【4.JOIN】チューニング
pref_id prefecture
1 Hokkaido
2 Aomori
~~~ ~~~
41 Saga
pref_id name age
1 Tokugawa 121
2 Toyotomi 125
~~~~ ~~~~ ~~~~
41 Akechi 130
3 Inoue 90
■ people
:
■ people - age_idx
※ MySQLはクラスタインデックスのため主キー=テーブルで実際はツリーです。
・ 狙うべき動作
【4.JOIN】チューニング
mysql> EXPLAIN SELECT prefecture
FROM prefecture INNER JOIN people USING(pref_id)
WHERE people.age >= 120;
+--+-----------+----------+------+--------------------+-------+---------------+----+-----------+
|id|select_type|table |type |possible_keys |key | ref |rows|Extra |
+--+-----------+----------+------+--------------------+-------+---------------+----+-----------+
| 1|SIMPLE |people |range |pref_id_idx,age_idx |age_idx| NULL | 3|Using where|
| 1|SIMPLE |prefecture|eq_ref|pref_id |pref_id| people.pref_id| 1|Using where|
+--+-----------+----------+------+--------------------+-------+---------------+----+-----------+
外部表が入れ替
わった
mysql> CREATE INDEX age_idx ON people(age);
Query OK, 0 rows affected (24.97 sec)
ループは3回
1回のループに
つき1行だけ
• 3 x 1 行スキャン
• Before: 4.3sec → After: 0sec
Copyright (C) 2016 Yahoo Japan Corporation. All Rights Reserved. 無断引用・転載禁止
代表的なチューニング例
1. type=ALL または type=index で rows が大きい
2. Extra に Using temporary; Using filesort でrowsが大きい
3. select_type が DEPENDENT SUBQUERY
4. JOINにおいて2つ目以降のExtraにUsing whereが出力さてい
て rows が大きい
5. 大量更新
6. データ削除
【6.大量の更新】
バルクインサートにより性能向上
INSERT INTO quote_real_info (ask10_flag, ask10_order, ask10_price, … <170カラムぐらい>
VALUES (NULL, NULL, '1150’, '2012-06-13 15:10:00’, '0’, '900’, …),
(NULL, NULL, '1152’, '2012-06-13 15:10:01’, '0’, '300', …),
(NULL, NULL, '1153', '2012-06-13 15:10:00', '0', '100', …),
(NULL, NULL, '1250', '2012-06-13 15:10:01', '0', '920', …),
(NULL, NULL, '1151', '2012-06-13 15:10:00', '0', '500', …),
(NULL, NULL, '1155', '2012-06-13 15:10:01', '0', '150', …));5万レコード
/sec
INSERT INTO quote_real_info (ask10_flag, ask10_order, ask10_price, … <170カラムぐらい>
VALUES (NULL, NULL, '1150', '2012-06-13 15:10:00', '0', '900', …);
INSERT INTO quote_real_info (ask10_flag, ask10_order, ask10_price, … <170カラムぐらい>
VALUES (NULL, NULL, '1150', '2012-06-13 15:10:00', '0', '900', …);
:
:
【6.大量の更新】チューニング方法
• RDBは通常コミット毎にDiskに書き込む
•× Auto-Commit
• バルクインサートはサーバ・クライアント間の通信
回数を減らせるため、より高速
• 1件1件コミット
• 複数件コミット
• バルクインサート
高速
Copyright (C) 2016 Yahoo Japan Corporation. All Rights Reserved. 無断引用・転載禁止
代表的なチューニング例
1. type=ALL または type=index で rows が大きい
2. Extra に Using temporary; Using filesort でrowsが大きい
3. select_type が DEPENDENT SUBQUERY
4. JOINにおいて2つ目以降のExtraにUsing whereが出力さてい
て rows が大きい
5. 大量更新
6. データ削除
Copyright (C) 2016 Yahoo Japan Corporation. All Rights Reserved. 無断引用・転載禁止
【7.テーブルの削除】
• TRUNCATE = DROP + CREATE
• 注意:AUTO_INCREMENTがリセット
• 条件を指定したい
• パーティション化 + [DROP|TRUNCATE] PARTITION
DELETE FROM push_message;
TRUNCATE TABLE push_message ;
Copyright (C) 2016 Yahoo Japan Corporation. All Rights Reserved. 無断引用・転載禁止
チューニングの難しいクエリ
必要なデータが大きいもの
SELECT COUNT(*) FROM access_log;
SELECT SUM(a) FROM access_log WHERE data BETWEEN ‘1995-01-01’ AND NOW();
必要なデータが大きいものは遅い
• MySQLは1セッション=1スレッド=1CPU
• 作りから見直す必要がある
• 例) 集計テーブルを作り更新時に同時にカウ
ントアップする
Copyright (C) 2016 Yahoo Japan Corporation. All Rights Reserved. 無断引用・転載禁止
まとめ
まとめ
• カーディナリティとキーの指定順に注意
• スロークエリログで犯人を特定
• EXPLAINで分析
• チューニング方法は様々・ケースバイケース
• → 経験あるのみ!
Copyright (C) 2016 Yahoo Japan Corporation. All Rights Reserved. 無断引用・転載禁止
おしらせ
MySQL Casual Slack
• MySQL Casual の Slack (チャット)
• 「MySQL Casual Slack」 で検索
Copyright (C) 2015 Yahoo Japan Corporation. All Rights Reserved. 無断引用・転載禁止
64
ありがとうございました

Contenu connexe

Tendances

Java ORマッパー選定のポイント #jsug
Java ORマッパー選定のポイント #jsugJava ORマッパー選定のポイント #jsug
Java ORマッパー選定のポイント #jsugMasatoshi Tada
 
MongoDBが遅いときの切り分け方法
MongoDBが遅いときの切り分け方法MongoDBが遅いときの切り分け方法
MongoDBが遅いときの切り分け方法Tetsutaro Watanabe
 
MySQL勉強会 クエリチューニング編
MySQL勉強会 クエリチューニング編MySQL勉強会 クエリチューニング編
MySQL勉強会 クエリチューニング編MicroAd, Inc.(Engineer)
 
SQLアンチパターン - 開発者を待ち受ける25の落とし穴 (拡大版)
SQLアンチパターン - 開発者を待ち受ける25の落とし穴 (拡大版)SQLアンチパターン - 開発者を待ち受ける25の落とし穴 (拡大版)
SQLアンチパターン - 開発者を待ち受ける25の落とし穴 (拡大版)Takuto Wada
 
SQLアンチパターン(インデックスショットガン)
SQLアンチパターン(インデックスショットガン)SQLアンチパターン(インデックスショットガン)
SQLアンチパターン(インデックスショットガン)Tomoaki Uchida
 
トランザクションをSerializableにする4つの方法
トランザクションをSerializableにする4つの方法トランザクションをSerializableにする4つの方法
トランザクションをSerializableにする4つの方法Kumazaki Hiroki
 
PostgreSQLの関数属性を知ろう
PostgreSQLの関数属性を知ろうPostgreSQLの関数属性を知ろう
PostgreSQLの関数属性を知ろうkasaharatt
 
Dockerからcontainerdへの移行
Dockerからcontainerdへの移行Dockerからcontainerdへの移行
Dockerからcontainerdへの移行Kohei Tokunaga
 
PostgreSQLクエリ実行の基礎知識 ~Explainを読み解こう~
PostgreSQLクエリ実行の基礎知識 ~Explainを読み解こう~PostgreSQLクエリ実行の基礎知識 ~Explainを読み解こう~
PostgreSQLクエリ実行の基礎知識 ~Explainを読み解こう~Miki Shimogai
 
GoによるWebアプリ開発のキホン
GoによるWebアプリ開発のキホンGoによるWebアプリ開発のキホン
GoによるWebアプリ開発のキホンAkihiko Horiuchi
 
SQLアンチパターン - ナイーブツリー
SQLアンチパターン - ナイーブツリーSQLアンチパターン - ナイーブツリー
SQLアンチパターン - ナイーブツリーke-m kamekoopa
 
Redisの特徴と活用方法について
Redisの特徴と活用方法についてRedisの特徴と活用方法について
Redisの特徴と活用方法についてYuji Otani
 
MySQL・PostgreSQLだけで作る高速あいまい全文検索システム
MySQL・PostgreSQLだけで作る高速あいまい全文検索システムMySQL・PostgreSQLだけで作る高速あいまい全文検索システム
MySQL・PostgreSQLだけで作る高速あいまい全文検索システムKouhei Sutou
 
本当は恐ろしい分散システムの話
本当は恐ろしい分散システムの話本当は恐ろしい分散システムの話
本当は恐ろしい分散システムの話Kumazaki Hiroki
 
さいきんの InnoDB Adaptive Flushing (仮)
さいきんの InnoDB Adaptive Flushing (仮)さいきんの InnoDB Adaptive Flushing (仮)
さいきんの InnoDB Adaptive Flushing (仮)Takanori Sejima
 
SQLアンチパターン 幻の第26章「とりあえず削除フラグ」
SQLアンチパターン 幻の第26章「とりあえず削除フラグ」SQLアンチパターン 幻の第26章「とりあえず削除フラグ」
SQLアンチパターン 幻の第26章「とりあえず削除フラグ」Takuto Wada
 
マイクロサービス 4つの分割アプローチ
マイクロサービス 4つの分割アプローチマイクロサービス 4つの分割アプローチ
マイクロサービス 4つの分割アプローチ増田 亨
 
ゼロから作るKubernetesによるJupyter as a Service ー Kubernetes Meetup Tokyo #43
ゼロから作るKubernetesによるJupyter as a Service ー Kubernetes Meetup Tokyo #43ゼロから作るKubernetesによるJupyter as a Service ー Kubernetes Meetup Tokyo #43
ゼロから作るKubernetesによるJupyter as a Service ー Kubernetes Meetup Tokyo #43Preferred Networks
 
目grep入門 +解説
目grep入門 +解説目grep入門 +解説
目grep入門 +解説murachue
 

Tendances (20)

Java ORマッパー選定のポイント #jsug
Java ORマッパー選定のポイント #jsugJava ORマッパー選定のポイント #jsug
Java ORマッパー選定のポイント #jsug
 
MongoDBが遅いときの切り分け方法
MongoDBが遅いときの切り分け方法MongoDBが遅いときの切り分け方法
MongoDBが遅いときの切り分け方法
 
MySQL勉強会 クエリチューニング編
MySQL勉強会 クエリチューニング編MySQL勉強会 クエリチューニング編
MySQL勉強会 クエリチューニング編
 
SQLアンチパターン - 開発者を待ち受ける25の落とし穴 (拡大版)
SQLアンチパターン - 開発者を待ち受ける25の落とし穴 (拡大版)SQLアンチパターン - 開発者を待ち受ける25の落とし穴 (拡大版)
SQLアンチパターン - 開発者を待ち受ける25の落とし穴 (拡大版)
 
SQLアンチパターン(インデックスショットガン)
SQLアンチパターン(インデックスショットガン)SQLアンチパターン(インデックスショットガン)
SQLアンチパターン(インデックスショットガン)
 
トランザクションをSerializableにする4つの方法
トランザクションをSerializableにする4つの方法トランザクションをSerializableにする4つの方法
トランザクションをSerializableにする4つの方法
 
PostgreSQLの関数属性を知ろう
PostgreSQLの関数属性を知ろうPostgreSQLの関数属性を知ろう
PostgreSQLの関数属性を知ろう
 
Docker Compose 徹底解説
Docker Compose 徹底解説Docker Compose 徹底解説
Docker Compose 徹底解説
 
Dockerからcontainerdへの移行
Dockerからcontainerdへの移行Dockerからcontainerdへの移行
Dockerからcontainerdへの移行
 
PostgreSQLクエリ実行の基礎知識 ~Explainを読み解こう~
PostgreSQLクエリ実行の基礎知識 ~Explainを読み解こう~PostgreSQLクエリ実行の基礎知識 ~Explainを読み解こう~
PostgreSQLクエリ実行の基礎知識 ~Explainを読み解こう~
 
GoによるWebアプリ開発のキホン
GoによるWebアプリ開発のキホンGoによるWebアプリ開発のキホン
GoによるWebアプリ開発のキホン
 
SQLアンチパターン - ナイーブツリー
SQLアンチパターン - ナイーブツリーSQLアンチパターン - ナイーブツリー
SQLアンチパターン - ナイーブツリー
 
Redisの特徴と活用方法について
Redisの特徴と活用方法についてRedisの特徴と活用方法について
Redisの特徴と活用方法について
 
MySQL・PostgreSQLだけで作る高速あいまい全文検索システム
MySQL・PostgreSQLだけで作る高速あいまい全文検索システムMySQL・PostgreSQLだけで作る高速あいまい全文検索システム
MySQL・PostgreSQLだけで作る高速あいまい全文検索システム
 
本当は恐ろしい分散システムの話
本当は恐ろしい分散システムの話本当は恐ろしい分散システムの話
本当は恐ろしい分散システムの話
 
さいきんの InnoDB Adaptive Flushing (仮)
さいきんの InnoDB Adaptive Flushing (仮)さいきんの InnoDB Adaptive Flushing (仮)
さいきんの InnoDB Adaptive Flushing (仮)
 
SQLアンチパターン 幻の第26章「とりあえず削除フラグ」
SQLアンチパターン 幻の第26章「とりあえず削除フラグ」SQLアンチパターン 幻の第26章「とりあえず削除フラグ」
SQLアンチパターン 幻の第26章「とりあえず削除フラグ」
 
マイクロサービス 4つの分割アプローチ
マイクロサービス 4つの分割アプローチマイクロサービス 4つの分割アプローチ
マイクロサービス 4つの分割アプローチ
 
ゼロから作るKubernetesによるJupyter as a Service ー Kubernetes Meetup Tokyo #43
ゼロから作るKubernetesによるJupyter as a Service ー Kubernetes Meetup Tokyo #43ゼロから作るKubernetesによるJupyter as a Service ー Kubernetes Meetup Tokyo #43
ゼロから作るKubernetesによるJupyter as a Service ー Kubernetes Meetup Tokyo #43
 
目grep入門 +解説
目grep入門 +解説目grep入門 +解説
目grep入門 +解説
 

En vedette

20140711 MySQL Casual Talks vol.6 / 続・Amazon RDS Casual Talks
20140711 MySQL Casual Talks vol.6 / 続・Amazon RDS Casual Talks20140711 MySQL Casual Talks vol.6 / 続・Amazon RDS Casual Talks
20140711 MySQL Casual Talks vol.6 / 続・Amazon RDS Casual TalksMori Tetsuya
 
mysqlcasual6-fabric
mysqlcasual6-fabricmysqlcasual6-fabric
mysqlcasual6-fabricdoublemarket
 
N:1 Replication meets MHA
N:1 Replication meets MHAN:1 Replication meets MHA
N:1 Replication meets MHAdo_aki
 
mysqlcasual6-next-key-lock
mysqlcasual6-next-key-lockmysqlcasual6-next-key-lock
mysqlcasual6-next-key-lockkarupanerura
 
My sql casual talks vol.6
My sql casual talks vol.6My sql casual talks vol.6
My sql casual talks vol.6Satoshi Suzuki
 
TokuDB試してみる
TokuDB試してみるTokuDB試してみる
TokuDB試してみるyoku0825
 
片手間MySQLチューニング戦略
片手間MySQLチューニング戦略片手間MySQLチューニング戦略
片手間MySQLチューニング戦略yoku0825
 

En vedette (8)

20140711 MySQL Casual Talks vol.6 / 続・Amazon RDS Casual Talks
20140711 MySQL Casual Talks vol.6 / 続・Amazon RDS Casual Talks20140711 MySQL Casual Talks vol.6 / 続・Amazon RDS Casual Talks
20140711 MySQL Casual Talks vol.6 / 続・Amazon RDS Casual Talks
 
mysqlcasual6-fabric
mysqlcasual6-fabricmysqlcasual6-fabric
mysqlcasual6-fabric
 
N:1 Replication meets MHA
N:1 Replication meets MHAN:1 Replication meets MHA
N:1 Replication meets MHA
 
MHA on AWS+Rails
MHA on AWS+RailsMHA on AWS+Rails
MHA on AWS+Rails
 
mysqlcasual6-next-key-lock
mysqlcasual6-next-key-lockmysqlcasual6-next-key-lock
mysqlcasual6-next-key-lock
 
My sql casual talks vol.6
My sql casual talks vol.6My sql casual talks vol.6
My sql casual talks vol.6
 
TokuDB試してみる
TokuDB試してみるTokuDB試してみる
TokuDB試してみる
 
片手間MySQLチューニング戦略
片手間MySQLチューニング戦略片手間MySQLチューニング戦略
片手間MySQLチューニング戦略
 

Similaire à ヤフー社内でやってるMySQLチューニングセミナー大公開

Maatkit で MySQL チューニング
Maatkit で MySQL チューニングMaatkit で MySQL チューニング
Maatkit で MySQL チューニングKensuke Nagae
 
PostgreSQL13 新機能紹介
PostgreSQL13 新機能紹介PostgreSQL13 新機能紹介
PostgreSQL13 新機能紹介Satoshi Hirata
 
HandlerSocket plugin for MySQL
HandlerSocket plugin for MySQLHandlerSocket plugin for MySQL
HandlerSocket plugin for MySQLakirahiguchi
 
20160929_InnoDBの全文検索を使ってみた by 株式会社インサイトテクノロジー 中村範夫
20160929_InnoDBの全文検索を使ってみた by 株式会社インサイトテクノロジー 中村範夫20160929_InnoDBの全文検索を使ってみた by 株式会社インサイトテクノロジー 中村範夫
20160929_InnoDBの全文検索を使ってみた by 株式会社インサイトテクノロジー 中村範夫Insight Technology, Inc.
 
MySQL日本語利用徹底入門
MySQL日本語利用徹底入門MySQL日本語利用徹底入門
MySQL日本語利用徹底入門Mikiya Okuno
 
Washingtondc b20161214 (2/3)
Washingtondc b20161214 (2/3)Washingtondc b20161214 (2/3)
Washingtondc b20161214 (2/3)Toshiyuki Shimono
 
C# 7.2 with .NET Core 2.1
C# 7.2 with .NET Core 2.1C# 7.2 with .NET Core 2.1
C# 7.2 with .NET Core 2.1信之 岩永
 
Introduction of Oracle Database Architecture(抜粋版) - JPOUG Oracle Database入学式 ...
Introduction of Oracle Database Architecture(抜粋版) - JPOUG Oracle Database入学式 ...Introduction of Oracle Database Architecture(抜粋版) - JPOUG Oracle Database入学式 ...
Introduction of Oracle Database Architecture(抜粋版) - JPOUG Oracle Database入学式 ...Ryota Watabe
 
MySQL 5.7 InnoDB 日本語全文検索(その2)
MySQL 5.7 InnoDB 日本語全文検索(その2)MySQL 5.7 InnoDB 日本語全文検索(その2)
MySQL 5.7 InnoDB 日本語全文検索(その2)yoyamasaki
 
Ruby科学データ処理ツールの開発 NArrayとPwrake
Ruby科学データ処理ツールの開発 NArrayとPwrakeRuby科学データ処理ツールの開発 NArrayとPwrake
Ruby科学データ処理ツールの開発 NArrayとPwrakeMasahiro Tanaka
 
Osc shimane-2016-do-postgres-dream-of-graph-database
Osc shimane-2016-do-postgres-dream-of-graph-databaseOsc shimane-2016-do-postgres-dream-of-graph-database
Osc shimane-2016-do-postgres-dream-of-graph-databaseToshi Harada
 
2019年度 若手技術者向け講座 実行計画
2019年度 若手技術者向け講座 実行計画2019年度 若手技術者向け講座 実行計画
2019年度 若手技術者向け講座 実行計画keki3
 
ActiveRecordでレガシーテーブルにつないだ話
ActiveRecordでレガシーテーブルにつないだ話ActiveRecordでレガシーテーブルにつないだ話
ActiveRecordでレガシーテーブルにつないだ話ryonext Shimamoto
 
MariaDB 10.3 概要
MariaDB 10.3 概要 MariaDB 10.3 概要
MariaDB 10.3 概要 GOTO Satoru
 
MySQL 5.5 Update #denatech
MySQL 5.5 Update #denatechMySQL 5.5 Update #denatech
MySQL 5.5 Update #denatechMikiya Okuno
 

Similaire à ヤフー社内でやってるMySQLチューニングセミナー大公開 (20)

Maatkit で MySQL チューニング
Maatkit で MySQL チューニングMaatkit で MySQL チューニング
Maatkit で MySQL チューニング
 
PostgreSQL13 新機能紹介
PostgreSQL13 新機能紹介PostgreSQL13 新機能紹介
PostgreSQL13 新機能紹介
 
HandlerSocket plugin for MySQL
HandlerSocket plugin for MySQLHandlerSocket plugin for MySQL
HandlerSocket plugin for MySQL
 
20160929_InnoDBの全文検索を使ってみた by 株式会社インサイトテクノロジー 中村範夫
20160929_InnoDBの全文検索を使ってみた by 株式会社インサイトテクノロジー 中村範夫20160929_InnoDBの全文検索を使ってみた by 株式会社インサイトテクノロジー 中村範夫
20160929_InnoDBの全文検索を使ってみた by 株式会社インサイトテクノロジー 中村範夫
 
MySQL日本語利用徹底入門
MySQL日本語利用徹底入門MySQL日本語利用徹底入門
MySQL日本語利用徹底入門
 
Washingtondc b20161214 (2/3)
Washingtondc b20161214 (2/3)Washingtondc b20161214 (2/3)
Washingtondc b20161214 (2/3)
 
20150630_MySQL勉強会
20150630_MySQL勉強会20150630_MySQL勉強会
20150630_MySQL勉強会
 
C# 7.2 with .NET Core 2.1
C# 7.2 with .NET Core 2.1C# 7.2 with .NET Core 2.1
C# 7.2 with .NET Core 2.1
 
Introduction of Oracle Database Architecture(抜粋版) - JPOUG Oracle Database入学式 ...
Introduction of Oracle Database Architecture(抜粋版) - JPOUG Oracle Database入学式 ...Introduction of Oracle Database Architecture(抜粋版) - JPOUG Oracle Database入学式 ...
Introduction of Oracle Database Architecture(抜粋版) - JPOUG Oracle Database入学式 ...
 
Cpu cache arch
Cpu cache archCpu cache arch
Cpu cache arch
 
MySQL 5.7 InnoDB 日本語全文検索(その2)
MySQL 5.7 InnoDB 日本語全文検索(その2)MySQL 5.7 InnoDB 日本語全文検索(その2)
MySQL 5.7 InnoDB 日本語全文検索(その2)
 
Ruby科学データ処理ツールの開発 NArrayとPwrake
Ruby科学データ処理ツールの開発 NArrayとPwrakeRuby科学データ処理ツールの開発 NArrayとPwrake
Ruby科学データ処理ツールの開発 NArrayとPwrake
 
Osc shimane-2016-do-postgres-dream-of-graph-database
Osc shimane-2016-do-postgres-dream-of-graph-databaseOsc shimane-2016-do-postgres-dream-of-graph-database
Osc shimane-2016-do-postgres-dream-of-graph-database
 
2019年度 若手技術者向け講座 実行計画
2019年度 若手技術者向け講座 実行計画2019年度 若手技術者向け講座 実行計画
2019年度 若手技術者向け講座 実行計画
 
pg_trgmと全文検索
pg_trgmと全文検索pg_trgmと全文検索
pg_trgmと全文検索
 
Maatkitの紹介
Maatkitの紹介Maatkitの紹介
Maatkitの紹介
 
Mysql charset
Mysql charsetMysql charset
Mysql charset
 
ActiveRecordでレガシーテーブルにつないだ話
ActiveRecordでレガシーテーブルにつないだ話ActiveRecordでレガシーテーブルにつないだ話
ActiveRecordでレガシーテーブルにつないだ話
 
MariaDB 10.3 概要
MariaDB 10.3 概要 MariaDB 10.3 概要
MariaDB 10.3 概要
 
MySQL 5.5 Update #denatech
MySQL 5.5 Update #denatechMySQL 5.5 Update #denatech
MySQL 5.5 Update #denatech
 

Plus de Yahoo!デベロッパーネットワーク

ヤフーでは開発迅速性と品質のバランスをどう取ってるか
ヤフーでは開発迅速性と品質のバランスをどう取ってるかヤフーでは開発迅速性と品質のバランスをどう取ってるか
ヤフーでは開発迅速性と品質のバランスをどう取ってるかYahoo!デベロッパーネットワーク
 
データの価値を最大化させるためのデザイン~データビジュアライゼーションの方法~ #devsumi 17-E-2
データの価値を最大化させるためのデザイン~データビジュアライゼーションの方法~ #devsumi 17-E-2データの価値を最大化させるためのデザイン~データビジュアライゼーションの方法~ #devsumi 17-E-2
データの価値を最大化させるためのデザイン~データビジュアライゼーションの方法~ #devsumi 17-E-2Yahoo!デベロッパーネットワーク
 
ヤフーを支えるセキュリティ ~サイバー攻撃を防ぐエンジニアの仕事とは~ #yjtc
ヤフーを支えるセキュリティ ~サイバー攻撃を防ぐエンジニアの仕事とは~ #yjtcヤフーを支えるセキュリティ ~サイバー攻撃を防ぐエンジニアの仕事とは~ #yjtc
ヤフーを支えるセキュリティ ~サイバー攻撃を防ぐエンジニアの仕事とは~ #yjtcYahoo!デベロッパーネットワーク
 
Yahoo! JAPANのIaaSを支えるKubernetesクラスタ、アップデート自動化への挑戦 #yjtc
Yahoo! JAPANのIaaSを支えるKubernetesクラスタ、アップデート自動化への挑戦 #yjtcYahoo! JAPANのIaaSを支えるKubernetesクラスタ、アップデート自動化への挑戦 #yjtc
Yahoo! JAPANのIaaSを支えるKubernetesクラスタ、アップデート自動化への挑戦 #yjtcYahoo!デベロッパーネットワーク
 
ヤフーのAIプラットフォーム紹介 ~AIテックカンパニーを支えるデータ基盤~ #yjtc
ヤフーのAIプラットフォーム紹介 ~AIテックカンパニーを支えるデータ基盤~ #yjtcヤフーのAIプラットフォーム紹介 ~AIテックカンパニーを支えるデータ基盤~ #yjtc
ヤフーのAIプラットフォーム紹介 ~AIテックカンパニーを支えるデータ基盤~ #yjtcYahoo!デベロッパーネットワーク
 
新技術を使った次世代の商品の見せ方 ~ヤフオク!のマルチビュー機能~ #yjtc
新技術を使った次世代の商品の見せ方 ~ヤフオク!のマルチビュー機能~ #yjtc新技術を使った次世代の商品の見せ方 ~ヤフオク!のマルチビュー機能~ #yjtc
新技術を使った次世代の商品の見せ方 ~ヤフオク!のマルチビュー機能~ #yjtcYahoo!デベロッパーネットワーク
 
PC版Yahoo!メールリニューアル ~サービスのUI/UX統合と改善プロセス~ #yjtc
PC版Yahoo!メールリニューアル ~サービスのUI/UX統合と改善プロセス~ #yjtcPC版Yahoo!メールリニューアル ~サービスのUI/UX統合と改善プロセス~ #yjtc
PC版Yahoo!メールリニューアル ~サービスのUI/UX統合と改善プロセス~ #yjtcYahoo!デベロッパーネットワーク
 
モブデザインによる多職種チームのコミュニケーション改善 #yjtc
モブデザインによる多職種チームのコミュニケーション改善 #yjtcモブデザインによる多職種チームのコミュニケーション改善 #yjtc
モブデザインによる多職種チームのコミュニケーション改善 #yjtcYahoo!デベロッパーネットワーク
 
ユーザーの地域を考慮した検索入力補助機能の改善の試み #yjtc
ユーザーの地域を考慮した検索入力補助機能の改善の試み #yjtcユーザーの地域を考慮した検索入力補助機能の改善の試み #yjtc
ユーザーの地域を考慮した検索入力補助機能の改善の試み #yjtcYahoo!デベロッパーネットワーク
 

Plus de Yahoo!デベロッパーネットワーク (20)

ゼロから始める転移学習
ゼロから始める転移学習ゼロから始める転移学習
ゼロから始める転移学習
 
継続的なモデルモニタリングを実現するKubernetes Operator
継続的なモデルモニタリングを実現するKubernetes Operator継続的なモデルモニタリングを実現するKubernetes Operator
継続的なモデルモニタリングを実現するKubernetes Operator
 
ヤフーでは開発迅速性と品質のバランスをどう取ってるか
ヤフーでは開発迅速性と品質のバランスをどう取ってるかヤフーでは開発迅速性と品質のバランスをどう取ってるか
ヤフーでは開発迅速性と品質のバランスをどう取ってるか
 
オンプレML基盤on Kubernetes パネルディスカッション
オンプレML基盤on Kubernetes パネルディスカッションオンプレML基盤on Kubernetes パネルディスカッション
オンプレML基盤on Kubernetes パネルディスカッション
 
LakeTahoe
LakeTahoeLakeTahoe
LakeTahoe
 
オンプレML基盤on Kubernetes 〜Yahoo! JAPAN AIPF〜
オンプレML基盤on Kubernetes 〜Yahoo! JAPAN AIPF〜オンプレML基盤on Kubernetes 〜Yahoo! JAPAN AIPF〜
オンプレML基盤on Kubernetes 〜Yahoo! JAPAN AIPF〜
 
Persistent-memory-native Database High-availability Feature
Persistent-memory-native Database High-availability FeaturePersistent-memory-native Database High-availability Feature
Persistent-memory-native Database High-availability Feature
 
データの価値を最大化させるためのデザイン~データビジュアライゼーションの方法~ #devsumi 17-E-2
データの価値を最大化させるためのデザイン~データビジュアライゼーションの方法~ #devsumi 17-E-2データの価値を最大化させるためのデザイン~データビジュアライゼーションの方法~ #devsumi 17-E-2
データの価値を最大化させるためのデザイン~データビジュアライゼーションの方法~ #devsumi 17-E-2
 
eコマースと実店舗の相互利益を目指したデザイン #yjtc
eコマースと実店舗の相互利益を目指したデザイン #yjtceコマースと実店舗の相互利益を目指したデザイン #yjtc
eコマースと実店舗の相互利益を目指したデザイン #yjtc
 
ヤフーを支えるセキュリティ ~サイバー攻撃を防ぐエンジニアの仕事とは~ #yjtc
ヤフーを支えるセキュリティ ~サイバー攻撃を防ぐエンジニアの仕事とは~ #yjtcヤフーを支えるセキュリティ ~サイバー攻撃を防ぐエンジニアの仕事とは~ #yjtc
ヤフーを支えるセキュリティ ~サイバー攻撃を防ぐエンジニアの仕事とは~ #yjtc
 
Yahoo! JAPANのIaaSを支えるKubernetesクラスタ、アップデート自動化への挑戦 #yjtc
Yahoo! JAPANのIaaSを支えるKubernetesクラスタ、アップデート自動化への挑戦 #yjtcYahoo! JAPANのIaaSを支えるKubernetesクラスタ、アップデート自動化への挑戦 #yjtc
Yahoo! JAPANのIaaSを支えるKubernetesクラスタ、アップデート自動化への挑戦 #yjtc
 
ビッグデータから人々のムードを捉える #yjtc
ビッグデータから人々のムードを捉える #yjtcビッグデータから人々のムードを捉える #yjtc
ビッグデータから人々のムードを捉える #yjtc
 
サイエンス領域におけるMLOpsの取り組み #yjtc
サイエンス領域におけるMLOpsの取り組み #yjtcサイエンス領域におけるMLOpsの取り組み #yjtc
サイエンス領域におけるMLOpsの取り組み #yjtc
 
ヤフーのAIプラットフォーム紹介 ~AIテックカンパニーを支えるデータ基盤~ #yjtc
ヤフーのAIプラットフォーム紹介 ~AIテックカンパニーを支えるデータ基盤~ #yjtcヤフーのAIプラットフォーム紹介 ~AIテックカンパニーを支えるデータ基盤~ #yjtc
ヤフーのAIプラットフォーム紹介 ~AIテックカンパニーを支えるデータ基盤~ #yjtc
 
Yahoo! JAPAN Tech Conference 2022 Day2 Keynote #yjtc
Yahoo! JAPAN Tech Conference 2022 Day2 Keynote #yjtcYahoo! JAPAN Tech Conference 2022 Day2 Keynote #yjtc
Yahoo! JAPAN Tech Conference 2022 Day2 Keynote #yjtc
 
新技術を使った次世代の商品の見せ方 ~ヤフオク!のマルチビュー機能~ #yjtc
新技術を使った次世代の商品の見せ方 ~ヤフオク!のマルチビュー機能~ #yjtc新技術を使った次世代の商品の見せ方 ~ヤフオク!のマルチビュー機能~ #yjtc
新技術を使った次世代の商品の見せ方 ~ヤフオク!のマルチビュー機能~ #yjtc
 
PC版Yahoo!メールリニューアル ~サービスのUI/UX統合と改善プロセス~ #yjtc
PC版Yahoo!メールリニューアル ~サービスのUI/UX統合と改善プロセス~ #yjtcPC版Yahoo!メールリニューアル ~サービスのUI/UX統合と改善プロセス~ #yjtc
PC版Yahoo!メールリニューアル ~サービスのUI/UX統合と改善プロセス~ #yjtc
 
モブデザインによる多職種チームのコミュニケーション改善 #yjtc
モブデザインによる多職種チームのコミュニケーション改善 #yjtcモブデザインによる多職種チームのコミュニケーション改善 #yjtc
モブデザインによる多職種チームのコミュニケーション改善 #yjtc
 
「新しいおうち探し」のためのAIアシスト検索 #yjtc
「新しいおうち探し」のためのAIアシスト検索 #yjtc「新しいおうち探し」のためのAIアシスト検索 #yjtc
「新しいおうち探し」のためのAIアシスト検索 #yjtc
 
ユーザーの地域を考慮した検索入力補助機能の改善の試み #yjtc
ユーザーの地域を考慮した検索入力補助機能の改善の試み #yjtcユーザーの地域を考慮した検索入力補助機能の改善の試み #yjtc
ユーザーの地域を考慮した検索入力補助機能の改善の試み #yjtc
 

Dernier

論文紹介:Content-Aware Token Sharing for Efficient Semantic Segmentation With Vis...
論文紹介:Content-Aware Token Sharing for Efficient Semantic Segmentation With Vis...論文紹介:Content-Aware Token Sharing for Efficient Semantic Segmentation With Vis...
論文紹介:Content-Aware Token Sharing for Efficient Semantic Segmentation With Vis...Toru Tamaki
 
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略Ryo Sasaki
 
Open Source UN-Conference 2024 Kawagoe - 独自OS「DaisyOS GB」の紹介
Open Source UN-Conference 2024 Kawagoe - 独自OS「DaisyOS GB」の紹介Open Source UN-Conference 2024 Kawagoe - 独自OS「DaisyOS GB」の紹介
Open Source UN-Conference 2024 Kawagoe - 独自OS「DaisyOS GB」の紹介Yuma Ohgami
 
TSAL operation mechanism and circuit diagram.pdf
TSAL operation mechanism and circuit diagram.pdfTSAL operation mechanism and circuit diagram.pdf
TSAL operation mechanism and circuit diagram.pdftaisei2219
 
【早稲田AI研究会 講義資料】3DスキャンとTextTo3Dのツールを知ろう!(Vol.1)
【早稲田AI研究会 講義資料】3DスキャンとTextTo3Dのツールを知ろう!(Vol.1)【早稲田AI研究会 講義資料】3DスキャンとTextTo3Dのツールを知ろう!(Vol.1)
【早稲田AI研究会 講義資料】3DスキャンとTextTo3Dのツールを知ろう!(Vol.1)Hiroki Ichikura
 
スマートフォンを用いた新生児あやし動作の教示システム
スマートフォンを用いた新生児あやし動作の教示システムスマートフォンを用いた新生児あやし動作の教示システム
スマートフォンを用いた新生児あやし動作の教示システムsugiuralab
 
論文紹介:Automated Classification of Model Errors on ImageNet
論文紹介:Automated Classification of Model Errors on ImageNet論文紹介:Automated Classification of Model Errors on ImageNet
論文紹介:Automated Classification of Model Errors on ImageNetToru Tamaki
 
論文紹介:Semantic segmentation using Vision Transformers: A survey
論文紹介:Semantic segmentation using Vision Transformers: A survey論文紹介:Semantic segmentation using Vision Transformers: A survey
論文紹介:Semantic segmentation using Vision Transformers: A surveyToru Tamaki
 
SOPを理解する 2024/04/19 の勉強会で発表されたものです
SOPを理解する       2024/04/19 の勉強会で発表されたものですSOPを理解する       2024/04/19 の勉強会で発表されたものです
SOPを理解する 2024/04/19 の勉強会で発表されたものですiPride Co., Ltd.
 

Dernier (9)

論文紹介:Content-Aware Token Sharing for Efficient Semantic Segmentation With Vis...
論文紹介:Content-Aware Token Sharing for Efficient Semantic Segmentation With Vis...論文紹介:Content-Aware Token Sharing for Efficient Semantic Segmentation With Vis...
論文紹介:Content-Aware Token Sharing for Efficient Semantic Segmentation With Vis...
 
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略
 
Open Source UN-Conference 2024 Kawagoe - 独自OS「DaisyOS GB」の紹介
Open Source UN-Conference 2024 Kawagoe - 独自OS「DaisyOS GB」の紹介Open Source UN-Conference 2024 Kawagoe - 独自OS「DaisyOS GB」の紹介
Open Source UN-Conference 2024 Kawagoe - 独自OS「DaisyOS GB」の紹介
 
TSAL operation mechanism and circuit diagram.pdf
TSAL operation mechanism and circuit diagram.pdfTSAL operation mechanism and circuit diagram.pdf
TSAL operation mechanism and circuit diagram.pdf
 
【早稲田AI研究会 講義資料】3DスキャンとTextTo3Dのツールを知ろう!(Vol.1)
【早稲田AI研究会 講義資料】3DスキャンとTextTo3Dのツールを知ろう!(Vol.1)【早稲田AI研究会 講義資料】3DスキャンとTextTo3Dのツールを知ろう!(Vol.1)
【早稲田AI研究会 講義資料】3DスキャンとTextTo3Dのツールを知ろう!(Vol.1)
 
スマートフォンを用いた新生児あやし動作の教示システム
スマートフォンを用いた新生児あやし動作の教示システムスマートフォンを用いた新生児あやし動作の教示システム
スマートフォンを用いた新生児あやし動作の教示システム
 
論文紹介:Automated Classification of Model Errors on ImageNet
論文紹介:Automated Classification of Model Errors on ImageNet論文紹介:Automated Classification of Model Errors on ImageNet
論文紹介:Automated Classification of Model Errors on ImageNet
 
論文紹介:Semantic segmentation using Vision Transformers: A survey
論文紹介:Semantic segmentation using Vision Transformers: A survey論文紹介:Semantic segmentation using Vision Transformers: A survey
論文紹介:Semantic segmentation using Vision Transformers: A survey
 
SOPを理解する 2024/04/19 の勉強会で発表されたものです
SOPを理解する       2024/04/19 の勉強会で発表されたものですSOPを理解する       2024/04/19 の勉強会で発表されたものです
SOPを理解する 2024/04/19 の勉強会で発表されたものです
 

ヤフー社内でやってるMySQLチューニングセミナー大公開

  • 3. Yahoo! JAPANのRDB環境 • 11g RAC Enterprise Edition • 約200DB • サーバ 200台, Exadata もあるよ • MySQL 5.1 (RR,Mixed) Percona 5.5 (RR,Mixed) Percona 5.6 (RC,RBR,GTID) • 約500DB • サーバ 300台 Oracle Database MySQL Percona
  • 4. 4
  • 5. 自己紹介 Copyright (C) 2016 Yahoo Japan Corporation. All Rights Reserved. 無断引用・転載禁止 5 • 三谷 智史(@mita2) • 所属 DBMS技術 RDB専門部隊 13名 • DB Administration 黒帯
  • 6. DBAあるある • へんなクエリ流されて、負荷が爆発 • SQLがスパゲッティすぎて解読不能 Copyright (C) 2016 Yahoo Japan Corporation. All Rights Reserved. 無断引用・転載禁止 6 RDBを正しく使ってもらうために、 社内でセミナーを実施しています。
  • 7. ヤフー社内でやってる MySQLチューニングセミナー大公開 Copyright (C) 2016 Yahoo Japan Corporation. All Rights Reserved. 無断引用・転載禁止 7
  • 8. ご注意 • 個人の経験をもとに記載しています。間違った情報が含ま れてたりするかもしれません。 • Version 5.5 を前提に記載しております。最新のバージョ ンでは改善されているケースもあります。 Copyright (C) 2016 Yahoo Japan Corporation. All Rights Reserved. 無断引用・転載禁止 8
  • 9. 本日の流れ 1. インデックスについて 2. SQLチューニング手順 1. 重いクエリの洗い出し 2. 実行計画の確認 3. SQLチューニング例 ※ InnoDBを前提。MyISAMはもう卒業しましょう。 Copyright (C) 2016 Yahoo Japan Corporation. All Rights Reserved. 無断引用・転載禁止
  • 11. • インデックスはツリー構造 • データはソートされている • リーフノードに値と行のPKを格納 なぜ、インデックスで高速化するのか? PK col1 time 1 a 11:15 2 f 01:10 3 d 03:01 : : : SELECT * FROM t WHERE col1 = ‘f’ インデックス対象 a-p r-z a pk=1 d pk=3 f pk=2 p pk=9 r pk=4 t pk=5
  • 12. カーディナリティ mysql> show index from t; +-----+----------+----------+------------+-<SNIP>-+-----------+-------------+ |Table|Non_unique| Key_name |Seq_in_index| | Collation | Cardinality | +-----+----------+----------+------------+--------+-----------+-------------+ | t | 0| PRIMARY | 1| | A | 5 | +-----+----------+----------+------------+--------+-----------+-------------+ 1 row in set (0.00 sec) インデックス内のユニークな値 の多さを表した指数 Copyright (C) 2016 Yahoo Japan Corporation. All Rights Reserved. 無断引用・転載禁止
  • 13. カーディナリティとは • カーディナリティが低いと効果が少ない • カーディナリティが高いデータの例 • AUTO_INCREMENT、住所、更新日時 • カーディナリティが低いデータの例 • フラグ、カテゴリ、都道府県 Copyright (C) 2016 Yahoo Japan Corporation. All Rights Reserved. 無断引用・転載禁止
  • 14. なぜ効果が少ないのか? 0 pk=1 pk=3 pk=5 : : : 1 pk=2 pk=4 pk=6 : : : PK is_pk_even_num (PKが偶数か?) time 1 0 11:15 2 1 12:31 3 0 13:44 4 1 14:01 : : : 1000000 1 20:01 SELECT * FROM t WHERE is_pk_even_num = 1 AND time <= 12:00 • 半分までしか絞り込めない • インデックスを経由することによる オーバーヘッドが無視できない インデックス対象 × 50万回
  • 15. PK is_pk_1000multi (PKが1000の倍数?) time 1 0 11:15 : 0 12:31 1000 1 13:44 : : 14:01 : : : 1000000 1 20:01 例外 0 pk=1 pk=2 pk=3 : : : 1 pk=1000 pk=2000 pk=3000 : SELECT * FROM t WHERE is_pk_1000multi = 1 AND time <= 12:00 • 分布が偏っていれば効果が大きくなる • 条件によって効果が異なる インデックス対象 × 1000回 Copyright (C) 2016 Yahoo Japan Corporation. All Rights Reserved. 無断引用・転載禁止
  • 16. Left-Most-Index 以下のインデックスは同じ? 違います インデックスA. CREATE INDEX idxA1 ON mytable (col1); CREATE INDEX idxA2 ON mytable (col2); インデックスB. CREATE INDEX idxB1 ON mytable (col1, col2); インデックスC. CREATE INDEX idxC1 ON mytable (col2, col1); Copyright (C) 2016 Yahoo Japan Corporation. All Rights Reserved. 無断引用・転載禁止
  • 17. 複合インデックスでは指定順が重要 a pk=1 9 a pk=2 8 b pk=3 7 b pk=4 6 5 pk=1 c 6 pk=4 b 7 pk=2 b 8 pk=3 a インデックスB. CREATE INDEX idxB1 ON mytable (col1, col2); インデックスC. CREATE INDEX idxC1 ON mytable (col2, col1); a b~c 5~6 7~9 col2col1 col1col2 c pk=5 5 9 pk=5 a
  • 18. 複合インデックスでは指定順が重要 絞り込み対象カラム → 1.WHRER col1 = ‘x’ 2.WHERE col2 = ‘x’ 3.WHERE col1 = ‘x’ AND col2 = ‘x’ インデックスA idxA1 が利用される idxA2 が利用される idxA1, idxA2 どちらかが利用される。 ※ インデックスB idxB1 が利用される インデックスは利 用されない idxB1 が利用される。 idxA1, idxA2より高速。 インデックスC インデックスは利 用されない idxC1 が利用される idxC1が利用される。 idxA1, idxA2より高速。 ※ 場合によってはインデックスマージ インデックスA. CREATE INDEX idxA1 ON mytable (col1); CREATE INDEX idxA2 ON mytable (col2); インデックスB. CREATE INDEX idxB1 ON mytable (col1, col2); インデックスC. CREATE INDEX idxC1 ON mytable (col2, col1);
  • 19. インデックスを貼るときのポイント • カーディナリティの高いカラムを選ぶ • 複合インデックスのカラムの順に注意 • 更新性能・キャッシュ効率が低下するため、 必要なものだけに貼る Copyright (C) 2016 Yahoo Japan Corporation. All Rights Reserved. 無断引用・転載禁止
  • 21. SQLチューニングの手順 1. 重いクエリランキングを出す 2. 実行計画を確認する 3. チューニング 1. SQLの書き換え 2. インデックスを貼る 3. テーブル構成をみなおす etc Copyright (C) 2016 Yahoo Japan Corporation. All Rights Reserved. 無断引用・転載禁止
  • 22. SQLチューニングの手順 1. 重いクエリランキングを出す 2. 実行計画を確認する 3. チューニング 1. SQLの書き換え 2. インデックスを貼る 3. テーブル構成をみなおす etc Copyright (C) 2016 Yahoo Japan Corporation. All Rights Reserved. 無断引用・転載禁止
  • 23. 重いSQLの洗い出し方 STEP1 スロークエリーログに全SQLを記録 $ sudo rm mysqld-slow.log $ mysql –u user_name –p mysql> SET GLOBAL long_query_time = 0; mysql> SET GLOBAL log_slow_verbosity=full; mysql> FLUSH LOGS; # User@Host: user[user] @ [1.2.3.4] # Query_time: 0.067361 Lock_time: 0.000030 Rows_sent: 16 Rows_examined: 121031 SET timestamp=1346772142; SELECT zpam.zip_cd FROM zip_area_mast zpam WHERE zpam.point_cd = 11276 AND zpam.del_flag = 0; : 実行時間 テーブルロックした時間 行ロックした時間はカウン トされていので注意! 結果の行数 スキャンした行数
  • 24. • Percona Tookit の pt-query-digest で集計 重いSQLの洗い出し方 STEP2 $ sudo pt-query-digest --group-by fingerprint¥ --order-by Query_time:sum ¥ --since '2015-06-14 00:00:00' --until '2015-06-14 23:59:59' ¥ mysqld-slow.log 合計実行時間でソート オプション ソート条件 Query_time:avg 平均実行時間 Query_time:sum 合計実行時間 InnoDB_IO_r_bytes:sum バッファプールにヒットせず、DISKから読み取った データ量 Copyright (C) 2016 Yahoo Japan Corporation. All Rights Reserved. 無断引用・転載禁止
  • 25. 集計結果 # Query 5: 39.92 QPS, 229.19kx concurrency, ID 0x72BFE142E32896BD at byte 88442 # Time range: 2015-10-29 23:00:00 to 23:59:59 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= # Count 31 143676 # Exec time 11 660s 150us 623ms 5ms 18ms 10ms 490us # Lock time 20 13s 32us 5ms 91us 113us 30us 89us # Rows sent 0 264.02k 0 4 1.88 2.90 0.69 1.96 # Rows examine 0 264.02k 0 4 1.88 2.90 0.69 1.96 # Rows affecte 0 0 0 0 0 0 0 0 # Rows read 0 264.02k 0 4 1.88 2.90 0.69 1.96 # Bytes sent 0 16.80M 83 171 122.61 143.84 17.33 124.25 # Merge passes 0 0 0 0 0 0 0 0 # Tmp tables 0 0 0 0 0 0 0 0 # Tmp disk tbl 0 0 0 0 0 0 0 0 # Tmp tbl size 0 0 0 0 0 0 0 0 # Query size 18 26.14M 148 271 190.81 246.02 51.01 143.84 # InnoDB: # IO r bytes 9 786.66M 0 80.00k 5.61k 15.96k 9.17k 0 # IO r ops 9 49.17k 0 5 0.35 0.99 0.57 0 # IO r wait 14 569s 0 620ms 4ms 17ms 10ms 0 <省略> SELECT topic_id FROM weather WHERE (consumeruri = ‘abc') AND (consumeruri_type = 'android')¥G 合計実行回数 平均実行時間 (1クエリあたり) レスポンス行数(1クエリあたり) クエリ 処理過程で読み込んだ行数 (1クエリあたり) キャッシュヒットせずに DISKから読んだバイト数
  • 26. SQLチューニングの手順 1. 重いクエリランキングを出す 2. 実行計画を確認する 3. チューニング 1. SQLの書き換え 2. インデックスを貼る 3. テーブル構成をみなおす etc Copyright (C) 2016 Yahoo Japan Corporation. All Rights Reserved. 無断引用・転載禁止
  • 27. 実行計画の確認 • 実行計画=クエリの処理の流れ • 「EXPLAIN」をクエリの先頭に付ける • 更新系クエリはSELECTに書き換え UPDATE t SET col = newvalue WHERE condition = ‘x’; EXPLAIN SELECT col FROM t WHERE condition = ‘x’; Copyright (C) 2016 Yahoo Japan Corporation. All Rights Reserved. 無断引用・転載禁止
  • 28. EXPLAINの結果の例 mysql> EXPLAIN SELECT t1.pk, t1.col1, t2.col2 FROM t1 INNER JOIN t2 ON (t1.pk = t2.fk) WHERE t1.pk = 1; +----+------------+------+------+--------------------+--------+--------+------+-----+-------------+ | id | select_type| table| type | possible_keys | key | key_len| ref | rows| Extra | +----+------------+------+------+--------------------+--------+--------+------+-----+-------------+ | 1 | SIMPLE | t1 | const| PRIMARY,pk_col1_idx| PRIMARY| 4 | const| 1| | | 1 | SIMPLE | t2 | ALL | NULL | NULL | NULL | NULL | 5| Using where | +----+------------+------+------+--------------------+--------+--------+------+-----+-------------+ カラム 説明 id SELECTごとに振られるID。処理順ではない点に注意。 select_type SELECTの種類。SIMPLE, SUBQUERY, UNIONなど。 type テーブルへのアクセス方法。インデックスの利用有無、読取範囲などがわかる。 possible_keys 利用可能なインデックス。 key 実際に利用されたインデックス。possible_keys からインデックスの内容や統計情報を加味して、選択さ れたインデックス。 key_len 読み取ったインデックスのバイト数。 ref 比較するカラム。constの場合は定数(WHERE x = 1のような場合)。 rows スキャンする見積もり行数。JOINやサブクエリが関係する場合は外部表のrows × 内部表のrowsがス キャンする行になる。 Extra その他の情報
  • 29. SQLチューニングの手順 1. 重いクエリランキングを出す 2. 実行計画を確認する 3. チューニング 1. SQLの書き換え 2. インデックスを貼る 3. テーブル構成をみなおす etc Copyright (C) 2016 Yahoo Japan Corporation. All Rights Reserved. 無断引用・転載禁止
  • 31. 代表的なチューニング例 1. type=ALL または type=index で rows が大きい 2. Extra に Using temporary; Using filesort でrowsが大きい 3. select_type が DEPENDENT SUBQUERY 4. JOINにおいて2つ目以降のExtraにUsing whereが出力さてい て rows が大きい 5. 大量更新 6. データ削除 Copyright (C) 2016 Yahoo Japan Corporation. All Rights Reserved. 無断引用・転載禁止
  • 32. 代表的なチューニング例 1. type=ALL または type=index で rows が大きい 2. Extra に Using temporary; Using filesort でrowsが大きい 3. select_type が DEPENDENT SUBQUERY 4. JOINにおいて2つ目以降のExtraにUsing whereが出力さてい て rows が大きい 5. 大量更新 6. データ削除 Copyright (C) 2016 Yahoo Japan Corporation. All Rights Reserved. 無断引用・転載禁止
  • 33. 【1.フルスキャン】 TYPE=ALL mysql> EXPLAIN SELECT push_id FROM push_info WHERE deleted=1 AND datediff(now(), mod_date) > '180'; +--+-----------+---------+----+-------------+----+-------+----+-------+--------------------------+ |id|select_type|table |type|possible_keys|key |key_len|ref |rows |Extra | +--+-----------+---------+----+-------------+----+-------+----+-------+--------------------------+ |1 |SIMPLE |push_info|ALL |NULL |NULL|NULL |NULL|1115182|Using where; | +--+-----------+---------+----+-------------+----+-------+----+-------+--------------------------+ mysql> SHOW INDEX FROM push_info; +-----------+------------+--------------------+--+----------+--------+------+------------+ | Table | Non_unique | Key_name |~| Sub_part | Packed | Null | Index_type | +-----------+------------+--------------------+--+----------+--------+------+------------+ | push_info | 0 | PRIMARY |~| NULL | NULL | | BTREE | +-----------+------------+--------------------+--+----------+--------+------+------------+ • mod_dateとdeletedにインデックスを貼るべき • 関数を適用した場合インデックスは効かない • すべての行に対してdatediffを実行してるのも× • mod_date < date_sub(NOW(), INTERVAL 180 DAY) と書くべき 全部読み込み 行数多い 111万行に対し て絞り込み
  • 34. インデックスが効かない条件 Extra 関数 WHERE datediff(now(), mod_date) > '180' 式 WHERE col1 / 2 = 0 否定構文 WHERE col1 != 3 LIKE検索 ※ 前方一致除く WHERE col1 LIKE ‘%string%’ WHERE col1 LIKE ‘%string’ Copyright (C) 2016 Yahoo Japan Corporation. All Rights Reserved. 無断引用・転載禁止
  • 35. 【1.フルスキャン】チューニング結果 mysql> CREATE INDEX idx01 ON push_info(deleted, mod_date); mysql> EXPLAIN SELECT push_id FROM push_info WHERE deleted=1 AND mod_date < date_sub(NOW(), INTERVAL 180 DAY); +----+-------------+-----------+-------+-------+------+------+--------------------------+ | id | select_type | table | type | key | ref | rows | Extra | +----+-------------+-----------+-------+-------+------+------+--------------------------+ | 1 | SIMPLE | push_info | range | idx01 | NULL | 10 | Using index | +----+-------------+-----------+-------+-------+------+------+--------------------------+ インデックスの 範囲読み込み 行数が10行 インデックスだ けで解決でき るクエリ • Before: 380msec → After: 0msec Copyright (C) 2016 Yahoo Japan Corporation. All Rights Reserved. 無断引用・転載禁止
  • 36. 代表的なチューニング例 1. type=ALL または type=index で rows が大きい 2. Extra に Using temporary; Using filesort でrowsが大きい 3. select_type が DEPENDENT SUBQUERY 4. JOINにおいて2つ目以降のExtraにUsing whereが出力さていて rows が大きい 5. 大量更新 6. データ削除 Copyright (C) 2016 Yahoo Japan Corporation. All Rights Reserved. 無断引用・転載禁止
  • 37. 【2.ソート】 mysql> EXPLAIN SELECT order_time,seller_id,image_id,item_id,<省略> FROM order_master WHERE is_hidden_page = '0' ORDER BY order_time DESC LIMIT 20; +--+-----------+--------------+----+---------------+----+----------+-----------------------------+ |id|select_type| table |type| possible_keys |key | rows | Extra | +--+-----------+--------------+----+---------------+----+----------+-----------------------------+ | 1|SIMPLE | order_master |ALL | NULL |NULL| 12200494 | Using where; Using filesort | +--+-----------+--------------+----+---------------+----+----------+-----------------------------+ • is_hidden_page は殆どの行で0 • カーディナリティが低いため× • ソートにインデックスは有効か? • LIMIT句がある場合に効果が高い 1200万件 ソートしている Copyright (C) 2016 Yahoo Japan Corporation. All Rights Reserved. 無断引用・転載禁止
  • 38. 【2.ソート】チューニング結果 mysql> CREATE INDEX OM_OTM ON order_master (order_time); mysql> EXPLAIN SELECT order_time,seller_id,image_id,item_id,<省略> FROM order_master WHERE is_hidden_page = '0' ORDER BY order_time DESC LIMIT 20; +--+-------------+--------------+-----+---------------+--------+------+-------------+ |id| select_type | table |type | possible_keys | key | rows | Extra | +--+-------------+--------------+-----+---------------+--------+------+-------------+ | 1| SIMPLE | order_master |index| NULL | OM_OTM | 20 | Using where | +--+-------------+--------------+-----+---------------+--------+------+-------------+ 20個だけ取る • インデックスはソート済みのため、ソートが不要 • 上位20件だけ取ったら、処理を終了 • Before: 4300sec → After: 0sec ソートがなくなるインデックス利用 Copyright (C) 2016 Yahoo Japan Corporation. All Rights Reserved. 無断引用・転載禁止
  • 39. 【2.ソート】 CALC_FOUND_ROWSはNG • SQL_CALC_FOUND_ROWS句 • 条件にマッチしたレコードが全部で何件あったかを返す • LIMIT句と一緒に使う • 「全部で何件」= LIMIT句がないのと同じ Copyright (C) 2016 Yahoo Japan Corporation. All Rights Reserved. 無断引用・転載禁止
  • 40. 【2.ソート】 考慮事項 • 1度に使われるインデックスは、 各テーブルにつき1つ • 選択が必要 • ソートを最適化する • 絞り込み(WHERE句)を最適化する Copyright (C) 2016 Yahoo Japan Corporation. All Rights Reserved. 無断引用・転載禁止
  • 41. 代表的なチューニング例 1. type=ALL または type=index で rows が大きい 2. Extra に Using temporary; Using filesort でrowsが大きい 3. select_type が DEPENDENT SUBQUERY 4. JOINにおいて2つ目以降のExtraにUsing whereが出力さていて rows が大きい 5. 大量更新 6. データ削除 Copyright (C) 2016 Yahoo Japan Corporation. All Rights Reserved. 無断引用・転載禁止
  • 42. 【3.相関サブクエリ】 mysql> EXPLAIN SELECT team_name FROM team WHERE team_id IN (SELECT team_id FROM member WHERE skill IN ("C")); +----+--------------------+--------+------+---------------+省略+------+-------------+ | id | select_type | table | type | possible_keys | | rows | Extra | +----+--------------------+--------+------+---------------+----+------+-------------+ | 1 | PRIMARY | team | ALL | NULL | | 3 | Using where | | 2 | DEPENDENT SUBQUERY | member | ALL | NULL | | 5 | Using where | +----+--------------------+--------+------+---------------+----+------+-------------+ team_id team_name 1 Team1 2 Team2 3 Team3 team_id member_name skill 1 Yahoo Taro C 1 Yahoo Jiro Python 2 Yahoo Hanako Ruby 2 Yahoo Saburo PHP 3 Yahoo Sirou Perl ■ member■ team Copyright (C) 2016 Yahoo Japan Corporation. All Rights Reserved. 無断引用・転載禁止
  • 43. 【3.相関サブクエリ】 期待する動作 team_id team_name 1 Team1 2 Team2 3 Team3 team_id member_name skill 1 Yahoo Taro C 1 Yahoo Jiro Python 2 Yahoo Hanako Ruby 2 Yahoo Saburo PHP 3 Yahoo Sirou Perl mysql> EXPLAIN SELECT team_name FROM team WHERE team_id IN (SELECT team_id FROM member WHERE skill IN ("C")); 最初に実行される ことを期待 ①skill=Cを探す②team_id=1を探す • memberテーブルを1回読み込む • teamテーブルを1回読み込む • 合計=5 + 3 = 8行の読み込みを期待する
  • 44. 【3.相関サブクエリ】 実際の動き mysql> EXPLAIN SELECT team_name FROM team WHERE team_id IN (SELECT team_id FROM member WHERE skill IN ("C")); team_id team_name 1 Team1 2 Team2 3 Team3 team_id member_name skill 1 Yahoo Taro C 1 Yahoo Jiro Python 2 Yahoo Hanako Ruby 2 Yahoo Saburo PHP 3 Yahoo Sirou Perl team_id =1 AND skill=C のレコードを探す • 合計= 3 + 3 * 5 = 18行の読み込み • 実行計画の「PRIMARY」は外部表(親)を示す • なぜ、期待どうりに動かないのか? • MySQLの仕様です。。。(5.6で改善されます)
  • 45. 【3.相関サブクエリ】 チューニング方法(1) mysql> CREATE INDEX idx_skill ON member(skill, team_id); mysql> EXPLAIN SELECT team_name FROM team WHERE team_id IN (SELECT team_id FROM member WHERE skill IN ("C")); +----+--------------------+--------+------+---------------+-----------+省略+------+-------------+ | id | select_type | table | type | possible_keys | key | | rows | Extra | +----+--------------------+--------+------+---------------+-----------+省略+------+-------------+ | 1 | PRIMARY | team | ALL | NULL | NULL | | 3 | Using where | | 2 | DEPENDENT SUBQUERY | member | ref | idx_skill | idx_skill | | 1 | Using where | +----+--------------------+--------+------+---------------+-----------+省略+------+-------------+ •サブクエリの実行にインデックスを利用 •3 + 3 * 1 = 6行に(見積もり) +----+--------------------+--------+------+---------------+省略+------+-------------+ | id | select_type | table | type | possible_keys | | rows | Extra | +----+--------------------+--------+------+---------------+----+------+-------------+ | 1 | PRIMARY | team | ALL | NULL | | 3 | Using where | | 2 | DEPENDENT SUBQUERY | member | ALL | NULL | | 5 | Using where | +----+--------------------+--------+------+---------------+----+------+-------------+ インデックス未使用
  • 46. 【3.相関サブクエリ】 チューニング方法(2) mysql> EXPLAIN SELECT team_name FROM team JOIN member USING(team_id) WHERE member.skill IN ("C"); +----+-------------+--------+--------+---------------+-----------+---------------------+------+ | id | select_type | table | type | possible_keys | key | ref | rows | +----+-------------+--------+--------+---------------+-----------+---------------------+------+ | 1 | SIMPLE | member | ref | idx_skill | idx_skill | const | 1 | | 1 | SIMPLE | team | eq_ref | PRIMARY | PRIMARY | test.member.team_id | 1 | +----+-------------+--------+--------+---------------+-----------+---------------------+------+ member表を先に読む • JOINに書き換える • 相関サブクエリ、だいたいJOINで書き直せる • オプティマイザが親子を自動判断 • member表を外部表(駆動表)にする +----+--------------------+--------+------+---------------+-----------+省略+------+-------------+ | id | select_type | table | type | possible_keys | key | | rows | Extra | +----+--------------------+--------+------+---------------+-----------+省略+------+-------------+ | 1 | PRIMARY | team | ALL | NULL | NULL | | 3 | Using where | | 2 | DEPENDENT SUBQUERY | member | ref | idx_skill | idx_skill | | 1 | Using where | +----+--------------------+--------+------+---------------+-----------+省略+------+-------------+
  • 47. 代表的なチューニング例 1. type=ALL または type=index で rows が大きい 2. Extra に Using temporary; Using filesort でrowsが大きい 3. select_type が DEPENDENT SUBQUERY 4. JOINにおいて2つ目以降のExtraにUsing whereが出力さ ていて rows が大きい 5. 大量更新 6. データ削除 Copyright (C) 2016 Yahoo Japan Corporation. All Rights Reserved. 無断引用・転載禁止
  • 48. 【4.JOIN】NL結合 • MySQLは「NestedLoop結合」のみをサポート • どんな結合条件でも対応可 • 最速とは限らないがバランスの良いアルゴリズム Copyright (C) 2016 Yahoo Japan Corporation. All Rights Reserved. 無断引用・転載禁止
  • 49. 【4.JOIN】NL結合 pref_id prefecture 1 Hokkaido 2 Aomori 3 Iwate pref_id name age 1 Yamada 20 1 Takana 33 2 Yamamoto 12 2 Ogawa 76 3 Inoue 90 ■ prefecture ■ people ■ cities - pref_id_idx mysql> EXPLAIN SELECT prefecture FROM prefecture INNER JOIN people USING(pref_id) WHERE people.age >= 120; +--+-----------+----------+----+-------------+-----------+--------------------+------+-----------+ |id|select_type|table |type|possible_keys|key | ref |rows |Extra | +--+-----------+----------+----+-------------+-----------+--------------------+------+-----------+ | 1|SIMPLE |prefecture|ALL |pref_id |NULL | NULL | 47| | | 1|SIMPLE |people |ref |pref_id_idx |pref_id_idx| prefecture.pref_id |173891|Using where| +--+-----------+----------+----+-------------+-----------+--------------------+------+-----------+ 上に表示される 表が外部表 pref_idカラムのインデックスを 利用して内部表からデータを取得 • NLはループの中にSELECTが入っているイメージ : : : :
  • 50. 【4.JOIN】NL結合 pref_id prefecture 1 Hokkaido 2 Aomori 3 Iwate pref_id name age 1 Yamada 20 1 Takana 33 2 Yamamoto 12 2 Ogawa 76 3 Inoue 90 ■ prefecture ■ people ■ cities - pref_id_idx mysql> EXPLAIN SELECT prefecture FROM prefecture INNER JOIN people USING(pref_id) WHERE people.age >= 120; +--+-----------+----------+----+-------------+-----------+--------------------+------+-----------+ |id|select_type|table |type|possible_keys|key | ref |rows |Extra | +--+-----------+----------+----+-------------+-----------+--------------------+------+-----------+ | 1|SIMPLE |prefecture|ALL |pref_id |NULL | NULL | 47| | | 1|SIMPLE |people |ref |pref_id_idx |pref_id_idx| prefecture.pref_id |173891|Using where| +--+-----------+----------+----+-------------+-----------+--------------------+------+-----------+ ちょっと大きめ : : : x47 17万行から age>=120を探す 47 x 17万行 スキャン 17万行
  • 51. 【4.JOIN】チューニング • ループ回数を少なくする • 結合条件以外の条件にマッチする件数を テーブルごとにカウント • 件数が少ないほうを外部表にする mysql> SELECT COUNT(*) FROM prefecture; +----------+ | COUNT(*) | +----------+ | 47 | +----------+ 1 row in set (0.00 sec) mysql> SELECT COUNT(*) FROM people where age >=120; +----------+ | COUNT(*) | +----------+ | 3 | +----------+ 1 row in set (0.70 sec) mysql> EXPLAIN SELECT prefecture FROM prefecture INNER JOIN people USING(pref_id) WHERE people.age >= 120; Copyright (C) 2016 Yahoo Japan Corporation. All Rights Reserved. 無断引用・転載禁止
  • 52. 【4.JOIN】チューニング pref_id prefecture 1 Hokkaido 2 Aomori ~~~ ~~~ 41 Saga pref_id name age 1 Tokugawa 121 2 Toyotomi 125 ~~~~ ~~~~ ~~~~ 41 Akechi 130 3 Inoue 90 ■ people : ■ people - age_idx ※ MySQLはクラスタインデックスのため主キー=テーブルで実際はツリーです。 ・ 狙うべき動作
  • 53. 【4.JOIN】チューニング mysql> EXPLAIN SELECT prefecture FROM prefecture INNER JOIN people USING(pref_id) WHERE people.age >= 120; +--+-----------+----------+------+--------------------+-------+---------------+----+-----------+ |id|select_type|table |type |possible_keys |key | ref |rows|Extra | +--+-----------+----------+------+--------------------+-------+---------------+----+-----------+ | 1|SIMPLE |people |range |pref_id_idx,age_idx |age_idx| NULL | 3|Using where| | 1|SIMPLE |prefecture|eq_ref|pref_id |pref_id| people.pref_id| 1|Using where| +--+-----------+----------+------+--------------------+-------+---------------+----+-----------+ 外部表が入れ替 わった mysql> CREATE INDEX age_idx ON people(age); Query OK, 0 rows affected (24.97 sec) ループは3回 1回のループに つき1行だけ • 3 x 1 行スキャン • Before: 4.3sec → After: 0sec Copyright (C) 2016 Yahoo Japan Corporation. All Rights Reserved. 無断引用・転載禁止
  • 54. 代表的なチューニング例 1. type=ALL または type=index で rows が大きい 2. Extra に Using temporary; Using filesort でrowsが大きい 3. select_type が DEPENDENT SUBQUERY 4. JOINにおいて2つ目以降のExtraにUsing whereが出力さてい て rows が大きい 5. 大量更新 6. データ削除
  • 55. 【6.大量の更新】 バルクインサートにより性能向上 INSERT INTO quote_real_info (ask10_flag, ask10_order, ask10_price, … <170カラムぐらい> VALUES (NULL, NULL, '1150’, '2012-06-13 15:10:00’, '0’, '900’, …), (NULL, NULL, '1152’, '2012-06-13 15:10:01’, '0’, '300', …), (NULL, NULL, '1153', '2012-06-13 15:10:00', '0', '100', …), (NULL, NULL, '1250', '2012-06-13 15:10:01', '0', '920', …), (NULL, NULL, '1151', '2012-06-13 15:10:00', '0', '500', …), (NULL, NULL, '1155', '2012-06-13 15:10:01', '0', '150', …));5万レコード /sec INSERT INTO quote_real_info (ask10_flag, ask10_order, ask10_price, … <170カラムぐらい> VALUES (NULL, NULL, '1150', '2012-06-13 15:10:00', '0', '900', …); INSERT INTO quote_real_info (ask10_flag, ask10_order, ask10_price, … <170カラムぐらい> VALUES (NULL, NULL, '1150', '2012-06-13 15:10:00', '0', '900', …); : :
  • 56. 【6.大量の更新】チューニング方法 • RDBは通常コミット毎にDiskに書き込む •× Auto-Commit • バルクインサートはサーバ・クライアント間の通信 回数を減らせるため、より高速 • 1件1件コミット • 複数件コミット • バルクインサート 高速 Copyright (C) 2016 Yahoo Japan Corporation. All Rights Reserved. 無断引用・転載禁止
  • 57. 代表的なチューニング例 1. type=ALL または type=index で rows が大きい 2. Extra に Using temporary; Using filesort でrowsが大きい 3. select_type が DEPENDENT SUBQUERY 4. JOINにおいて2つ目以降のExtraにUsing whereが出力さてい て rows が大きい 5. 大量更新 6. データ削除 Copyright (C) 2016 Yahoo Japan Corporation. All Rights Reserved. 無断引用・転載禁止
  • 58. 【7.テーブルの削除】 • TRUNCATE = DROP + CREATE • 注意:AUTO_INCREMENTがリセット • 条件を指定したい • パーティション化 + [DROP|TRUNCATE] PARTITION DELETE FROM push_message; TRUNCATE TABLE push_message ; Copyright (C) 2016 Yahoo Japan Corporation. All Rights Reserved. 無断引用・転載禁止
  • 60. 必要なデータが大きいもの SELECT COUNT(*) FROM access_log; SELECT SUM(a) FROM access_log WHERE data BETWEEN ‘1995-01-01’ AND NOW(); 必要なデータが大きいものは遅い • MySQLは1セッション=1スレッド=1CPU • 作りから見直す必要がある • 例) 集計テーブルを作り更新時に同時にカウ ントアップする Copyright (C) 2016 Yahoo Japan Corporation. All Rights Reserved. 無断引用・転載禁止
  • 62. まとめ • カーディナリティとキーの指定順に注意 • スロークエリログで犯人を特定 • EXPLAINで分析 • チューニング方法は様々・ケースバイケース • → 経験あるのみ! Copyright (C) 2016 Yahoo Japan Corporation. All Rights Reserved. 無断引用・転載禁止
  • 64. MySQL Casual Slack • MySQL Casual の Slack (チャット) • 「MySQL Casual Slack」 で検索 Copyright (C) 2015 Yahoo Japan Corporation. All Rights Reserved. 無断引用・転載禁止 64