ISUCON10 に参加して惨敗した。そして知らなかったことまとめ – DB編 –

  • 投稿者:
  • 投稿カテゴリー:MySQL

ISUCON10に参加して惨敗した。その後のDiscordや参加者記事で知らなかったことなどを調べたり試してみた。

MySQLのクエリキャッシュ

そもそもクエリキャッシュを有効にしてなかったorz
キャッシュヒット率はQcache_hits / ( Qcache_hits + Qcache_inserts + Qcache_not_cached ) で算出可能。

# vi /etc/mysql/my.cnf
query_cache_type = 1 を追加

# mysql -uroot -p

mysql> SHOW VARIABLES LIKE '%query_cache_%';
+------------------------------+----------+
| Variable_name                | Value    |
+------------------------------+----------+
| query_cache_limit            | 1048576  |
| query_cache_min_res_unit     | 4096     |
| query_cache_size             | 16777216 |
| query_cache_type             | ON       |
| query_cache_wlock_invalidate | OFF      |
+------------------------------+----------+
5 rows in set (0.00 sec)

mysql> SHOW STATUS LIKE 'Qcache%';
+-------------------------+----------+
| Variable_name           | Value    |
+-------------------------+----------+
| Qcache_free_blocks      | 1        | # クエリキャッシュ内の空きメモリブロック数
| Qcache_free_memory      | 16601384 | # クエリキャッシュ用の空きメモリ量
| Qcache_hits             | 7        | # クエリキャッシュヒット数
| Qcache_inserts          | 9        | # クエリキャッシュに追加されるクエリ数
| Qcache_lowmem_prunes    | 0        | # メモリ不足でクエリーキャッシュから削除されたクエリ数
| Qcache_not_cached       | 231      | # 非キャッシュクエリ数
| Qcache_queries_in_cache | 9        | # クエリキャッシュ内に登録されたクエリ数
| Qcache_total_blocks     | 21       | # クエリキャッシュ内のブロック合計数
+-------------------------+----------+
8 rows in set (0.00 sec)

pt-query-digest

・スローログをノーマライズ・集計し、人間が判断しやすい形式で出力させることが可能。
・Percona社が開発・配布するMySQL用のユーティリティーキットで「Percona Toolkit」の1つ。

# apt install percona-toolkit
...
# pt-query-digest slow.log

# 400ms user time, 20ms system time, 29.04M rss, 84.09M vsz
# Current date: Mon Sep 14 11:49:22 2020
# Hostname: team135-003
# Files: slow.log
# Overall: 705 total, 21 unique, 0.01 QPS, 0.00x concurrency _____________
# Time range: 2020-09-13T16:35:35 to 2020-09-14T06:25:01
# Attribute          total     min     max     avg     95%  stddev  median
# ============     ======= ======= ======= ======= ======= ======= =======
# Exec time             8s     2us      3s    11ms     3ms   170ms   152us
# Lock time           57ms       0     5ms    81us   204us   181us    57us
# Rows sent          1.75k       0     301    2.55   19.46   14.58    0.99
# Rows examine     876.54k       0  36.11k   1.24k 1012.63   5.66k    0.99
# Query size       351.14k      26     683  510.03  652.75  251.53  621.67

# Profile
# Rank Query ID           Response time Calls R/Call V/M   Item
# ==== ================== ============= ===== ====== ===== =============
#    1 0xF418F8958C3A84C3  3.3505 41.5%     6 0.5584  2.53 SELECT estate
#    2 0xD5E8472C4FDAEE41  3.1777 39.4%     9 0.3531  2.58 SELECT chair
#    3 0x85DF0F23BB694539  0.9487 11.7%     2 0.4743  0.92 SELECT estate
#    4 0x4F5BBA6F46285FBC  0.1663  2.1%     9 0.0185  0.00 SELECT chair
#    5 0xBB5556170BADF35E  0.0871  1.1%   531 0.0002  0.00 SELECT estate
# MISC 0xMISC              0.3442  4.3%   148 0.0023   0.0 <16 ITEMS>

# Query 1: 0.50 QPS, 0.28x concurrency, ID 0xF418F8958C3A84C3 at byte 492810
# Scores: V/M = 2.53
# Time range: 2020-09-13T18:01:19 to 2020-09-13T18:01:31
# Attribute    pct   total     min     max     avg     95%  stddev  median
# ============ === ======= ======= ======= ======= ======= ======= =======
# Count          0       6
# Exec time     41      3s    36us      3s   558ms      3s      1s    21ms
# Lock time      0   445us       0   205us    74us   204us    80us   116us
# Rows sent      3      60       0      20      10   19.46    9.73   19.46
# Rows examine  10  88.05k       0  29.39k  14.67k  28.66k  14.33k  28.66k
# Query size     0     700     116     117  116.67  112.70    0.00  112.70
# String:
# Databases    isuumo
# Hosts        10.161.35.101
# Users        isucon
# Query_time distribution
#   1us
#  10us  ################################################################
# 100us
#   1ms
#  10ms  ##########################################
# 100ms
#    1s  #####################
#  10s+
# Tables
#    SHOW TABLE STATUS FROM `isuumo` LIKE 'estate'\G
#    SHOW CREATE TABLE `isuumo`.`estate`\G
# EXPLAIN /*!50100 PARTITIONS*/
SELECT * FROM estate WHERE door_width >= 110 AND door_width < 150 ORDER BY popularity DESC, id ASC LIMIT 20 OFFSET 0\G

# Query 2: 0.01 QPS, 0.00x concurrency, ID 0xD5E8472C4FDAEE41 at byte 281849
# Scores: V/M = 2.58
# Time range: 2020-09-13T17:22:12 to 2020-09-13T17:43:56
# Attribute    pct   total     min     max     avg     95%  stddev  median
# ============ === ======= ======= ======= ======= ======= ======= =======
# Count          1       9
# Exec time     39      3s    51us      3s   353ms      3s   954ms    17ms
# Lock time      2     1ms       0   225us   146us   224us    79us   159us
# Rows sent      0       7       0       1    0.78    0.99    0.41    0.99
# Rows examine  23 205.08k       0  29.30k  22.79k  28.66k  11.91k  28.66k
# Query size     0     675      75      75      75      75       0      75
# String:
# Databases    isuumo
# Hosts        10.161.35.101
# Users        isucon
# Query_time distribution
#   1us
#  10us  #####################
# 100us
#   1ms
#  10ms  ################################################################
# 100ms
#    1s  ##########
#  10s+
# Tables
#    SHOW TABLE STATUS FROM `isuumo` LIKE 'chair'\G
#    SHOW CREATE TABLE `isuumo`.`chair`\G
# EXPLAIN /*!50100 PARTITIONS*/
SELECT COUNT(*) FROM chair WHERE width >= 110 AND width < 150 AND stock > 0\G

# Query 3: 0.00 QPS, 0.00x concurrency, ID 0x85DF0F23BB694539 at byte 287070
# Scores: V/M = 0.92
# Time range: 2020-09-13T16:38:01 to 2020-09-13T17:44:13
# Attribute    pct   total     min     max     avg     95%  stddev  median
# ============ === ======= ======= ======= ======= ======= ======= =======
# Count          0       2
# Exec time     11   949ms     7ms   941ms   474ms   941ms   660ms   474ms
# Lock time      0   492us   176us   316us   246us   316us    98us   246us
# Rows sent     29     531     230     301  265.50     301   50.20  265.50
# Rows examine   0   1.04k     460     602     531     602  100.41     531
# Query size     0     383     190     193  191.50     193    2.12  191.50
# String:
# Databases    isuumo
# Hosts        10.161.35.101
# Users        isucon
# Query_time distribution
#   1us
#  10us
# 100us
#   1ms  ################################################################
#  10ms
# 100ms  ################################################################
#    1s
#  10s+
# Tables
#    SHOW TABLE STATUS FROM `isuumo` LIKE 'estate'\G
#    SHOW CREATE TABLE `isuumo`.`estate`\G
# EXPLAIN /*!50100 PARTITIONS*/
SELECT * FROM estate WHERE latitude <= '35.926868653041' AND latitude >= '35.733136223134' AND longitude <= '139.64172363281' AND longitude >= '139.31488037109' ORDER BY popularity DESC, id ASC\G

# Query 4: 0.01 QPS, 0.00x concurrency, ID 0x4F5BBA6F46285FBC at byte 283764
# Scores: V/M = 0.00
# Time range: 2020-09-13T17:22:12 to 2020-09-13T17:43:56
# Attribute    pct   total     min     max     avg     95%  stddev  median
# ============ === ======= ======= ======= ======= ======= ======= =======
# Count          1       9
# Exec time      2   166ms    36us    21ms    18ms    21ms     6ms    20ms
# Lock time      2     1ms       0   243us   142us   236us    59us   138us
# Rows sent      8     160       0      20   17.78   19.46    6.12   19.46
# Rows examine  26 234.63k       0  29.38k  26.07k  28.66k   9.01k  28.66k
# Query size     0   1.05k     119     120  119.22  118.34       0  118.34
# String:
# Databases    isuumo
# Hosts        10.161.35.101
# Users        isucon
# Query_time distribution
#   1us
#  10us  ########
# 100us
#   1ms
#  10ms  ################################################################
# 100ms
#    1s
#  10s+
# Tables
#    SHOW TABLE STATUS FROM `isuumo` LIKE 'chair'\G
#    SHOW CREATE TABLE `isuumo`.`chair`\G
# EXPLAIN /*!50100 PARTITIONS*/
SELECT * FROM chair WHERE width >= 110 AND width < 150 AND stock > 0 ORDER BY popularity DESC, id ASC LIMIT 20 OFFSET 40\G

# Query 5: 0.13 QPS, 0.00x concurrency, ID 0xBB5556170BADF35E at byte 13203
# Scores: V/M = 0.00
# Time range: 2020-09-13T16:38:01 to 2020-09-13T17:44:13
# Attribute    pct   total     min     max     avg     95%  stddev  median
# ============ === ======= ======= ======= ======= ======= ======= =======
# Count         75     531
# Exec time      1    87ms    98us   453us   163us   214us    38us   152us
# Lock time     60    35ms    47us   214us    65us    80us    15us    57us
# Rows sent     20     370       0       1    0.70    0.99    0.46    0.99
# Rows examine   0     370       0       1    0.70    0.99    0.46    0.99
# Query size    97 341.63k     638     683  658.82  652.75   15.40  621.67
# String:
# Databases    isuumo
# Hosts        10.161.35.101
# Users        isucon
# Query_time distribution
#   1us
#  10us  #
# 100us  ################################################################
#   1ms
#  10ms
# 100ms
#    1s
#  10s+
# Tables
#    SHOW TABLE STATUS FROM `1` LIKE 'estate'\G
#    SHOW CREATE TABLE `1`.`estate`\G
# EXPLAIN /*!50100 PARTITIONS*/
SELECT * FROM estate WHERE id = '27762' AND ST_Contains(ST_PolygonFromText('POLYGON((35.750970 139.498901,35.750970 139.586792,35.753199 139.630737,35.757657 139.671936,35.773258 139.710388,35.782171 139.729614,35.920196 139.644470,35.944659 139.627991,35.953553 139.614258,35.960223 139.595032,35.960223 139.551086,35.951330 139.512634,35.949106 139.504395,35.940212 139.487915,35.924645 139.471436,35.902400 139.449463,35.860118 139.408264,35.842308 139.400024,35.826721 139.394531,35.784399 139.394531,35.764343 139.411011,35.757657 139.441223,35.753199 139.463196,35.750970 139.498901))'), ST_GeomFromText('POINT(35.801034 139.625385)'))\G

ノーマライズされた上でスローログが分析されるが、[EXPLAIN]項目はそのままEXPLAINできるように出力されている。
その提案をもとに改善する。

# mysql -uroot -p
Enter password:
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 28
Server version: 5.7.31-0ubuntu0.18.04.1-log (Ubuntu)

mysql> use isuumo

mysql> explain SELECT * FROM estate WHERE door_width >= 110 AND door_width < 150 ORDER BY popularity DESC, id ASC LIMIT 20 OFFSET 0\G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: estate
   partitions: NULL
         type: ALL
possible_keys: index_estate_width_height,index_estate_width_height_order
          key: NULL
      key_len: NULL
          ref: NULL
         rows: 28688
     filtered: 44.07
        Extra: Using where; Using filesort
1 row in set, 1 warning (0.00 sec)

MySQLTuner

・サーバのパフォーマンスの概観を表示し、推奨設定を提示してくれるツール

# apt install mysqltuner
...
# mysqltuner
 >>  MySQLTuner 1.7.2 - Major Hayden <major@mhtx.net>
 >>  Bug reports, feature requests, and downloads at http://mysqltuner.com/
 >>  Run with '--help' for additional options and output filtering

[--] Skipped version check for MySQLTuner script
[OK] Logged in using credentials from debian maintenance account.
[OK] Currently running supported MySQL version 5.7.31-0ubuntu0.18.04.1-log
[OK] Operating on 64-bit architecture

-------- Log file Recommendations ------------------------------------------------------------------
[--] Log file: /var/log/mysql/error.log(782B)
[OK] Log file /var/log/mysql/error.log exists
[OK] Log file /var/log/mysql/error.log is readable.
[OK] Log file /var/log/mysql/error.log is not empty
[OK] Log file /var/log/mysql/error.log is smaller than 32 Mb
[OK] /var/log/mysql/error.log doesn't contain any warning.
[!!] /var/log/mysql/error.log contains 5 error(s).
[--] 0 start(s) detected in /var/log/mysql/error.log
[--] 0 shutdown(s) detected in /var/log/mysql/error.log

-------- Storage Engine Statistics -----------------------------------------------------------------
[--] Status: +ARCHIVE +BLACKHOLE +CSV -FEDERATED +InnoDB +MEMORY +MRG_MYISAM +MyISAM +PERFORMANCE_SCHEMA
[--] Data in InnoDB tables: 51M (Tables: 7)
[OK] Total fragmented tables: 0

-------- Security Recommendations ------------------------------------------------------------------
[OK] There are no anonymous accounts for any database users
[!!] User 'root@localhost' has no password set.
[!!] User 'isucon@%' has user name as password.
[!!] User 'isucon@localhost' has user name as password.
[!!] User 'isucon@%' hasn't specific host restriction.
[--] There are 612 basic passwords in the list.

-------- CVE Security Recommendations --------------------------------------------------------------
[OK] NO SECURITY CVE FOUND FOR YOUR VERSION

-------- Performance Metrics -----------------------------------------------------------------------
[--] Up for: 23h 10m 5s (1K q [0.014 qps], 49 conn, TX: 1M, RX: 551K)
[--] Reads / Writes: 100% / 0%
[--] Binary logging is disabled
[--] Physical Memory     : 1.9G
[--] Max MySQL memory    : 4.1G
[--] Other process memory: 98.4M
[--] Total buffers: 2.1G global + 4.2M per thread (500 max threads)
[--] P_S Max memory usage: 72B
[--] Galera GCache Max memory usage: 0B
[!!] Maximum reached memory usage: 2.1G (107.19% of installed RAM)
[!!] Maximum possible memory usage: 4.1G (211.82% of installed RAM)
[!!] Overall possible memory usage with other process exceeded memory
[!!] Slow queries: 100% (1K/1K)
[OK] Highest usage of available connections: 0% (2/500)
[OK] Aborted connections: 0.00%  (0/49)
[!!] Query cache may be disabled by default due to mutex contention.
[!!] Query cache efficiency: 3.3% (34 cached / 1K selects)
[OK] Query cache prunes per day: 0
[OK] Sorts requiring temporary tables: 0% (0 temp sorts / 13 sorts)
[OK] No joins without indexes
[OK] Temporary tables created on disk: 0% (0 on disk / 27 total)
[OK] Thread cache hit rate: 95% (2 created / 49 connections)
[OK] Table cache hit rate: 60% (97 open / 160 opened)
[OK] Open file limit used: 0% (7/5K)
[OK] Table locks acquired immediately: 100% (110 immediate / 110 locks)

-------- Performance schema ------------------------------------------------------------------------
[--] Memory used by P_S: 72B
[--] Sys schema is installed.

-------- ThreadPool Metrics ------------------------------------------------------------------------
[--] ThreadPool stat is disabled.

-------- MyISAM Metrics ----------------------------------------------------------------------------
[!!] Key buffer used: 18.2% (3M used / 16M cache)
[OK] Key buffer size / total MyISAM indexes: 16.0M/43.0K
[!!] Read Key buffer hit rate: 50.0% (6 cached / 3 reads)

-------- InnoDB Metrics ----------------------------------------------------------------------------
[--] InnoDB is enabled.
[--] InnoDB Thread Concurrency: 0
[OK] InnoDB File per table is activated
[OK] InnoDB buffer pool / data size: 2.0G/51.3M
[!!] Ratio InnoDB log file size / InnoDB Buffer pool size (150 %): 1.5G * 2/2.0G should be equal 25%
[!!] InnoDB buffer pool instances: 8
[--] Number of InnoDB Buffer Pool Chunk : 16 for 8 Buffer Pool Instance(s)
[OK] Innodb_buffer_pool_size aligned with Innodb_buffer_pool_chunk_size & Innodb_buffer_pool_instances
[OK] InnoDB Read buffer efficiency: 96.79% (68237 hits/ 70499 total)
[!!] InnoDB Write Log efficiency: 0% (2 hits/ 0 total)
[OK] InnoDB log waits: 0.00% (0 waits / 2 writes)

-------- AriaDB Metrics ----------------------------------------------------------------------------
[--] AriaDB is disabled.

-------- TokuDB Metrics ----------------------------------------------------------------------------
[--] TokuDB is disabled.

-------- XtraDB Metrics ----------------------------------------------------------------------------
[--] XtraDB is disabled.

-------- RocksDB Metrics ---------------------------------------------------------------------------
[--] RocksDB is disabled.

-------- Spider Metrics ----------------------------------------------------------------------------
[--] Spider is disabled.

-------- Connect Metrics ---------------------------------------------------------------------------
[--] Connect is disabled.

-------- Galera Metrics ----------------------------------------------------------------------------
[--] Galera is disabled.

-------- Replication Metrics -----------------------------------------------------------------------
[--] Galera Synchronous replication: NO
[--] No replication slave(s) for this server.
[--] This is a standalone server.

-------- Recommendations ---------------------------------------------------------------------------
General recommendations:
    Control error line(s) into /var/log/mysql/error.log file
    Set up a Password for user with the following SQL statement ( SET PASSWORD FOR 'user'@'SpecificDNSorIp' = PASSWORD('secure_password'); )
    Set up a Secure Password for user@host ( SET PASSWORD FOR 'user'@'SpecificDNSorIp' = PASSWORD('secure_password'); )
    Restrict Host for user@% to user@SpecificDNSorIp
    MySQL started within last 24 hours - recommendations may be inaccurate
    Reduce your overall MySQL memory footprint for system stability
    Dedicate this server to your database for highest performance.
Variables to adjust:
  *** MySQL's maximum memory usage is dangerously high ***
  *** Add RAM before increasing MySQL buffer variables ***
    query_cache_size (=0)
    query_cache_type (=0)
    query_cache_limit (> 1M, or use smaller result sets)
    innodb_log_file_size * innodb_log_files_in_group should be equal to 1/4 of buffer pool size (=1G) if possible.
    innodb_buffer_pool_instances(=2)

参考

MySQL クエリキャッシュの概要と導入・評価方法
スローログの集計に便利な「pt-query-digest」を使ってみよう