チューニンガソン5の復讐

48
チチチチチチチチ 5 チチチ SH2 チチチチチチチチチチチ2013/07/29 MyNA July in 2013 yoku0825

Upload: yoku0825

Post on 12-May-2015

2.622 views

Category:

Technology


0 download

DESCRIPTION

2013/07/29のMyNA会の資料です。 奥野さんのブログ記事の一部(CC-BY-NC-SA)を含んでいるため、CC-BY-NC-SAです。

TRANSCRIPT

Page 1: チューニンガソン5の復讐

チューニンガソン 5 の復讐

~ SH2 さんの宿題をやってみた~

2013/07/29MyNA July in 2013

yoku0825

Page 2: チューニンガソン5の復讐

SH2 さんのブログ記事

チューニンガソン 5 の復習 MySQL 5.5 チート編&勉強会のお知らせ

http://d.hatena.ne.jp/sh2/20130304

に敬意を表して

Page 3: チューニンガソン5の復讐

\こんばんは/• I'm yoku0825, working as DBA for the

company which provides web-services.• Husband of my wife :)• Father of my son :)• I love sushi more than yakiniku :)

Of cource, I love yakiniku well.• MySQL? It's my delight :)

Page 4: チューニンガソン5の復讐

今日のテーマ• LT なので、チューニンガソン 5 の説明は

省略します。– レギュレーションとかはゼロスタートさんの

広報ブログをhttp://pr.zero-start.jp/archives/65730135.html

• 今回のチューニングは SH2 さんのブログ記事がベースです。– http://d.hatena.ne.jp/sh2/20130304

Page 5: チューニンガソン5の復讐

SH2 さんのチューニング (?)

Page 6: チューニンガソン5の復讐

やってみましょう

Page 7: チューニンガソン5の復讐

握 り つ ぶ し て い ま す

Page 8: チューニンガソン5の復讐

同じ文字列を返すようにできます

Page 9: チューニンガソン5の復讐

まあなんというか

Page 10: チューニンガソン5の復讐
Page 11: チューニンガソン5の復讐

( ´- ` ).oO ( MySQL Proxy でクエリ書き換えはいくらなんでもあんまりだろう

と思ったのは俺だけではないはず

Page 12: チューニンガソン5の復讐

そんなアナタに贈る

Page 13: チューニンガソン5の復讐

MySQL Proxy を使わずにmysqld を改造して

クエリキャッシュに載せるライフハック

Let's 魔改造

Page 14: チューニンガソン5の復讐

用意したもの• CentOS 6.3 の仮想マシン。– 1vCPU– 1GiB Memory– 230IOPS しかでなかった仮想 DISK

• MySQL 5.6.12 Source-Distributed• 男らしい潔さと大胆さ。• 後ろを振り返らない勇ましさ。• 最後は初心に返る謙虚さ。

Page 15: チューニンガソン5の復讐

まずは吊るしのスコアを測定$ python tgbench_mysql_2.py localhostQ0:0.00024Q1:31.04855Q2:21.24284Q3:20.81227Q4:81.48403Q5:77.68560Total:232.27354

$ python tgbench_mysql_2.py localhostQ0:0.00034Q1:19.70425Q2:19.93358Q3:20.23704Q4:76.66882Q5:76.79747Total:213.34149

Page 16: チューニンガソン5の復讐

うわっ…私の MySQL 、遅すぎ…?

My MySQL is slower than your MySQL :(

Page 17: チューニンガソン5の復讐

まあ、行きます。

まずは RESET QUERY CACHE を何とかしようず。

Page 18: チューニンガソン5の復讐

RESET QUERY CACHE の回避• RESET QUERY CACHEを処理する関数は

Query_cache::flush()2063 /* Remove all queries from cache */2064 2065 void Query_cache::flush()2066 {2067 DBUG_ENTER("Query_cache::flush");2068 if (is_disabled())2069 DBUG_VOID_RETURN;20702071 QC_DEBUG_SYNC("wait_in_query_cache_flush1");20722073 lock_and_suspend();2074 if (query_cache_size > 0)2075 {2076 DUMP(this);2077 flush_cache();2078 DUMP(this);2079 }20802081 DBUG_EXECUTE("check_querycache",query_cache.check_integrity(1););2082 unlock();2083 DBUG_VOID_RETURN;2084 }

Page 19: チューニンガソン5の復讐

RESET QUERY CACHE の回避• 男らしい潔さと大胆さを発揮。****************** 2064,2085 ****

void Query_cache::flush() {- DBUG_ENTER("Query_cache::flush");- if (is_disabled())- DBUG_VOID_RETURN;-- QC_DEBUG_SYNC("wait_in_query_cache_flush1");-- lock_and_suspend();- if (query_cache_size > 0)- {- DUMP(this);- flush_cache();- DUMP(this);- }-- DBUG_EXECUTE("check_querycache",query_cache.check_integrity(1););- unlock(); DBUG_VOID_RETURN; }

--- 2064,2069 ----

Page 20: チューニンガソン5の復讐

Q3, Q4, Q5 がクエリキャッシュから返るように

$ python tgbench_mysql_2.py localhostQ0:0.00024Q1:27.84138Q2:20.36092Q3:20.98092Q4:81.70963Q5:75.44204Total:226.33513

$ python tgbench_mysql_2.py localhostQ0:0.00019Q1:20.24178Q2:20.76213Q3:0.00057Q4:0.11970Q5:0.00879Total:41.13317

Page 21: チューニンガソン5の復讐

はい次。

NOW() 関数を何とかしようず。

Page 22: チューニンガソン5の復讐

NOW() 関数の回避• クエリーがクエリーキャッシュにのるべきか否かを判

定するのはQuery_cache::is_cacheable3702 TABLE_COUNTER_TYPE3703 Query_cache::is_cacheable(THD *thd, size_t query_len, const char *query,3704 LEX *lex,3705 TABLE_LIST *tables_used, uint8 *tables_type)3706 {3707 TABLE_COUNTER_TYPE table_count;3708 DBUG_ENTER("Query_cache::is_cacheable");37093710 if (query_cache_is_cacheable_query(lex) &&3711 (thd->variables.query_cache_type == 1 ||3712 (thd->variables.query_cache_type == 2 && (lex->select_lex.options &3713 OPTION_TO_QUERY_CACHE))))3714 {..3720 if (!(table_count= process_and_count_tables(thd, tables_used,3721 tables_type)))3722 DBUG_RETURN(0);37233724 if (thd->in_multi_stmt_transaction_mode() &&3725 ((*tables_type)&HA_CACHE_TBL_TRANSACT))3726 {3727 DBUG_PRINT("qcache", ("not in autocommin mode"));3728 DBUG_RETURN(0);3729 }3730 DBUG_PRINT("qcache", ("select is using %d tables", table_count));3731 DBUG_RETURN(table_count);3732 }

Page 23: チューニンガソン5の復讐

NOW() 関数の回避• 本当はNOW()だけ華麗にスルーしたかったけど、

手が込みそうなので後ろを振り返らない勇ましさを発揮。

****************** 3707,3716 **** TABLE_COUNTER_TYPE table_count; DBUG_ENTER("Query_cache::is_cacheable");

! if (query_cache_is_cacheable_query(lex) &&! (thd->variables.query_cache_type == 1 || (thd->variables.query_cache_type == 2 && (lex->select_lex.options &! OPTION_TO_QUERY_CACHE)))) { DBUG_PRINT("qcache", ("options: %lx %lx type: %u", (long) OPTION_TO_QUERY_CACHE,--- 3691,3699 ---- TABLE_COUNTER_TYPE table_count; DBUG_ENTER("Query_cache::is_cacheable");

! if (thd->variables.query_cache_type == 1 || (thd->variables.query_cache_type == 2 && (lex->select_lex.options &! OPTION_TO_QUERY_CACHE))) { DBUG_PRINT("qcache", ("options: %lx %lx type: %u", (long) OPTION_TO_QUERY_CACHE,

Page 24: チューニンガソン5の復讐

Q2 もクエリキャッシュから返るように

$ python tgbench_mysql_2.py localhostQ0:0.00030Q1:32.63952Q2:21.20478Q3:21.08606Q4:82.93199Q5:78.23889Total:236.10153

$ python tgbench_mysql_2.py localhostQ0:0.00021Q1:20.41031Q2:0.00031Q3:0.00014Q4:0.11961Q5:0.00984Total:20.54041

Page 25: チューニンガソン5の復讐

はい次。

AUTOCOMMIT を何とかしようず。

Page 26: チューニンガソン5の復讐

AUTOCOMMIT の壁• Bug #42197 の壁

http://bugs.mysql.com/bug.php?id=42197• 正直色々無理。• 俺が直せるならとっくに直ってるだろ。• vio で autocommit フラグを握りつぶそうかと

思ったけど、 sql/sql_cache.cc の中で完結したかった。

• トランザクション周りの判定を色々変えてみるも、そもそも my_hash_search で転んでるのでダメぽ。

Page 27: チューニンガソン5の復讐

結局

Page 28: チューニンガソン5の復讐

謙虚に初心に返ってみた• ALTER TABLE page Engine = MyISAM;• ALTER TABLE revision Engine = MyISAM;

'`, 、 '`, 、 ( ´∀ ` )'`, 、 '`, 、

Page 29: チューニンガソン5の復讐

これで全てがクエリキャッシュから返る

$ python tgbench_mysql_2.py localhostQ0:0.00031Q1:3.44232Q2:2.98533Q3:2.97978Q4:29.55061Q5:25.79326Total:64.75160

$ python tgbench_mysql_2.py localhostQ0:0.00018Q1:0.00016Q2:0.00010Q3:0.00033Q4:0.11568Q5:0.00785Total:0.12431

Page 30: チューニンガソン5の復讐

副作用$ time mysql -e "SELECT rev_id FROM wikipedia.revision ORDER BY RAND() LIMIT 5"+----------+| rev_id |+----------+| 43292141 || 35737287 || 45015288 || 39406805 || 44899598 |+----------+

real 0m4.259suser 0m0.006ssys 0m0.004s

$ time mysql -e "SELECT rev_id FROM wikipedia.revision ORDER BY RAND() LIMIT 5"+----------+| rev_id |+----------+| 43292141 || 35737287 || 45015288 || 39406805 || 44899598 |+----------+

real 0m0.027suser 0m0.005ssys 0m0.005s

Page 31: チューニンガソン5の復讐

ORDER BY RAND() でもクエリキャッシュから返るから DISK に優しい!

orz

Page 32: チューニンガソン5の復讐

副作用$ time mysql -e "SELECT rev_id, NOW() FROM wikipedia.revision LIMIT 5"+---------+---------------------+| rev_id | NOW() |+---------+---------------------+| 647678 | 2013-07-08 11:50:14 || 2168855 | 2013-07-08 11:50:14 || 2168856 | 2013-07-08 11:50:14 || 2168894 | 2013-07-08 11:50:14 || 2168972 | 2013-07-08 11:50:14 |+---------+---------------------+

real 0m0.031suser 0m0.007ssys 0m0.003s

$ time mysql -e "SELECT rev_id, NOW() FROM wikipedia.revision LIMIT 5"+---------+---------------------+| rev_id | NOW() |+---------+---------------------+| 647678 | 2013-07-08 11:50:14 || 2168855 | 2013-07-08 11:50:14 || 2168856 | 2013-07-08 11:50:14 || 2168894 | 2013-07-08 11:50:14 || 2168972 | 2013-07-08 11:50:14 |+---------+---------------------+

real 0m0.011suser 0m0.005ssys 0m0.004s

Page 33: チューニンガソン5の復讐

まるで REPEATABLE-READ!!

orz

Page 34: チューニンガソン5の復讐

日本よ、これが MySQL 5.6だッ!!

(c) @nippondanjihttp://nippondanji.blogspot.jp/2012/10/mysql-56.html

Page 35: チューニンガソン5の復讐

すいません調子乗りました orz

Page 36: チューニンガソン5の復讐

今回の魔改造の副産物

というか、魔改造が副産物だけど

Page 37: チューニンガソン5の復讐

information_schema.QUERY_CACHE_INFO

• MariaDB 10.0.2, 5.5.31 にもバックポートされた、クエリーキャッシュの中身を覗けるinformation_schema プラグイン

• 自力で書こうと頑張っていた頃に見つけて見事にやる気をなくす

• が、折角だから MySQL でも使えるようにパッチした

• 取り敢えずステージング環境に突っ込んで使ってる

Page 38: チューニンガソン5の復讐

こんな感じmysql55> SELECT * FROM information_schema.query_cache_info LIMIT 3\G*************************** 1. row *************************** STATEMENT_SCHEMA: tpcc STATEMENT_TEXT: SELECT i_price, i_name, i_data FROM item WHERE i_id = 16360 RESULT_BLOCKS_COUNT: 1 RESULT_BLOCKS_SIZE: 512RESULT_BLOCKS_SIZE_USED: 298*************************** 2. row *************************** STATEMENT_SCHEMA: tpcc STATEMENT_TEXT: SELECT i_price, i_name, i_data FROM item WHERE i_id = 39901 RESULT_BLOCKS_COUNT: 1 RESULT_BLOCKS_SIZE: 512RESULT_BLOCKS_SIZE_USED: 297*************************** 3. row *************************** STATEMENT_SCHEMA: tpcc STATEMENT_TEXT: SELECT i_price, i_name, i_data FROM item WHERE i_id = 2134 RESULT_BLOCKS_COUNT: 1 RESULT_BLOCKS_SIZE: 512RESULT_BLOCKS_SIZE_USED: 3023 rows in set (0.01 sec)

Page 39: チューニンガソン5の復讐

パッチはこちら

https://github.com/yoku0825/qc_info

Page 40: チューニンガソン5の復讐

MariaDB の JIRA にインプリメントのパッチがあるので

そのうち追加するかも

あと 5.6 で動かないのでそれも

Page 41: チューニンガソン5の復讐

MySQL 5.6 ではデフォルトで offになりましたが

しかも (for performance reasons) って中の人に書かれてたり。知ってるけどさ ( つ д ` )

http://bugs.mysql.com/bug.php?id=68241

Page 42: チューニンガソン5の復讐

読んでみると意外と面白かったりします

よく知られたところだから、想定する動作が判るってのが大き

Page 43: チューニンガソン5の復讐

\宣伝/

Page 44: チューニンガソン5の復讐

スパスパ MySQL やりたい

   ( ´∀ ` )y-~~        ↑このへんがスパスパ

Page 45: チューニンガソン5の復讐

本家

• 過去のイベントです。• http://atnd.org/events/33779• ハッシュタグなんてあったんですね!? #gdgdmysql• 参加されている面子的に、煙草飲みには肩身が狭そうな気配。• 煙草もやめられないけど MySQL もやめられない。

Page 46: チューニンガソン5の復讐

じゃあ作るしかない

Page 47: チューニンガソン5の復讐

というわけでスパスパ MySQL

9 月上旬にやるつもりです。

参加しても良いよって方は@yoku0825 までメンション下さい。

Page 48: チューニンガソン5の復讐

ご清聴ありがとうございました