私は現在、速度を上げるために継承したデータベースを最適化しようとしています。
サーバーはAmazon RDS db.m3.largeインスタンスです:
私の現在の戦略は、次のことです。
aggr_id
列に一意のインデックスを追加します(生産を中断せずにこれを適切に行う方法は?)現在のアプローチやその他のアイデアに関するフィードバックを得るためにこの投稿を作成しています。私は決してDBAではなく、単なるWeb開発者です。事前のおかげで、あらゆるフィードバックを歓迎します。私は必ず返信し、回答を承認してください!この投稿は、得られた洞察と見つかったリソースを使用して編集します。
すべて同じ形式の問題の表がいくつかあります。
| xxxxx | CREATE TABLE `xxxxx` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`aggr_id` int(11) NOT NULL,
`craft_id` int(11) NOT NULL,
`task_year` smallint(8) unsigned NOT NULL,
`hc1` mediumint(8) unsigned DEFAULT NULL,
......
`hc365` mediumint(8) unsigned DEFAULT NULL,
PRIMARY KEY (`id`,`task_year`),
KEY `IDX_AGGRLABORDAY` (`task_year`,`aggr_id`,`craft_id`)
) ENGINE=MyISAM AUTO_INCREMENT=50480037 DEFAULT CHARSET=latin1
/*!50500 PARTITION BY RANGE COLUMNS(task_year)
(PARTITION p1 VALUES LESS THAN (2012) ENGINE = MyISAM,
PARTITION p2 VALUES LESS THAN (2013) ENGINE = MyISAM,
PARTITION p3 VALUES LESS THAN (2014) ENGINE = MyISAM,
PARTITION p4 VALUES LESS THAN (2015) ENGINE = MyISAM,
PARTITION p5 VALUES LESS THAN (2016) ENGINE = MyISAM,
PARTITION p6 VALUES LESS THAN (2017) ENGINE = MyISAM,
PARTITION p7 VALUES LESS THAN (9999) ENGINE = MyISAM) */
問題のあるクエリの説明は次のとおりです。
explain DELETE FROM xxxxx WHERE aggr_id = 3000010;
+----+-------------+---------------------------+------+---------------+------+---------+------+----------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+---------------------------+------+---------------+------+---------+------+----------+-------------+
| 1 | SIMPLE | xxxxx | ALL | NULL | NULL | NULL | NULL | 46611048 | Using where |
+----+-------------+---------------------------+------+---------------+------+---------+------+----------+-------------+
1 row in set (0.05 sec)
以下はMySQLTunerの結果です。
[--] Assuming 7680 MB of physical memory
[!!] Assuming 0 MB of swap space (use --forceswap to specify)
[OK] Currently running supported MySQL version 5.6.21-log
-------- Storage Engine Statistics -------------------------------------------
[--] Status: +ARCHIVE +BLACKHOLE +CSV -FEDERATED +InnoDB +MRG_MYISAM
[--] Data in MyISAM tables: 274G (Tables: 75)
[--] Data in PERFORMANCE_SCHEMA tables: 0B (Tables: 52)
[--] Data in InnoDB tables: 7G (Tables: 227)
[!!] Total fragmented tables: 35
-------- Security Recommendations -------------------------------------------
[OK] All database users have passwords assigned
-------- Performance Metrics -------------------------------------------------
[--] Up for: 107d 15h 56m 50s (110M q [11.901 qps], 3M conn, TX: 14149B, RX: 108B)
[--] Reads / Writes: 58% / 42%
[--] Total buffers: 5.4G global + 1.5M per thread (604 max threads)
[OK] Maximum possible memory usage: 6.2G (83% of installed RAM)
[OK] Slow queries: 0% (17K/110M)
[OK] Highest usage of available connections: 29% (177/604)
[OK] Key buffer size / total MyISAM indexes: 16.0M/49.6G
[OK] Key buffer hit rate: 99.4% (25B cached / 155M reads)
[!!] Query cache is disabled
[OK] Sorts requiring temporary tables: 2% (133K temp sorts / 6M sorts)
[!!] Temporary tables created on disk: 62% (7M on disk / 11M total)
[OK] Thread cache hit rate: 74% (945K created / 3M connections)
[!!] Table cache hit rate: 0% (1K open / 674K opened)
[OK] Open file limit used: 3% (2K/65K)
[!!] Table locks acquired immediately: 78%
[!!] InnoDB buffer pool / data size: 5.3G/7.7G
[!!] InnoDB log waits: 1
-------- Recommendations -----------------------------------------------------
General recommendations:
Run OPTIMIZE TABLE to defragment tables for better performance
When making adjustments, make tmp_table_size/max_heap_table_size equal
Reduce your SELECT DISTINCT queries without LIMIT clauses
Increase table_open_cache gradually to avoid file descriptor limits
Read this before increasing table_open_cache over 64: http://bit.ly/1mi7c4C
Optimize queries and/or use InnoDB to reduce lock wait
Variables to adjust:
query_cache_type (=1)
tmp_table_size (> 16M)
max_heap_table_size (> 16M)
table_open_cache (> 2000)
innodb_buffer_pool_size (>= 7G)
innodb_log_buffer_size (>= 8M)
(私はあなたのポイントを見て、これを書いています。行動を起こす前に最後まで読んでください。私は少しずつベストアンサーを「開発」します-いくつかのことを学んでほしいと思います。)
DELETE FROM xxxxx WHERE aggr_id = 3000010;
すべてのパーティションのすべての行をスキャンする必要があります。これは、チューニングに関係なく、多くのI/Oを実行する必要があることを意味します。
これが一般的なクエリの場合は、
INDEX(aggr_id)
さらに良いのは変化です
KEY `IDX_AGGRLABORDAY` (`task_year`,`aggr_id`,`craft_id`)
通常、「パーティションキー」(task_year)は、インデックスではなく、インデックスのendで終了するのが最適です。この場合は、単に削除することもできます。 task_yearの使用はすべて「プルーニング」用であり、KEYが引き継ぐことができます。 INDEXをDROPし、以下を1つのALTERに追加します。
KEY `IDX_AGGRLABORDAY` (`aggr_id`,`craft_id`)
注意:テーブルはしばらくロックされます。
オンラインのINDEX操作があるInnoDBに切り替える必要があります。
チューナーの提案は通常より悪いようです:
Aggr_idを一意にすることができる場合は、おそらくそれを主キーにして、id
を削除する必要があります。パーティション化のため、一意性制約を設定できないことに注意してください。
ここでは2つのことが絡み合っていることに注意してください。InnoDBに切り替えて、aggr_idをPKにすることです。両方行う場合は、
PRIMARY KEY (aggr_id, craft_id, task_year)
セカンダリキーはありません。根拠:
InnoDBへの切り替えは、ほとんどの場合「良好」です。落とし穴については私のブログを参照してください: http://mysql.rjweb.org/doc.php/myisam2innodb そこにいる間、ここでパーティションの問題についてお読みください: http:// mysql .rjweb.org/doc.php/partitionmaint パーティショニングがうまくいっていないと結論するかもしれません。
All-InnoDBに移動すると、innodb_buffer_pool_size = 5Gおよびkey_buffer_size = 20Mになります。