web-dev-qa-db-ja.com

8.0でデータベースがめちゃくちゃに(そして奇妙に矛盾して)遅くなる

最近、大規模なDBを8.0に移動してみたところ、めちゃくちゃの速度が悪い(場合によっては100倍遅い)ことがわかりました。私は過去2日間、これをググるのに費やしてきましたが、すべてを試してみたが運がなかったような気がします。

いくつかの情報:新しいVMは新しいインスタンス用にスピンアップしました。RAMが同じで、SSDドライブが同じで、一般に古いものより高速であるはずですが、それでも実行できるので、 2つを比較します。

動作が遅いことが判明したクエリの1つをプルして、いくつかのテストを行いました。ここで、少し奇妙なことが起こります。新しいサーバーに運用データベースと開発データベースがあり、劇的に異なる速度が出ています。この特定のテーブルを最近コピーしたので、テーブル、構造、およびキーが3つの場所すべてで同一であることを知っています。 (現金とステータスはどちらもENUMであることに注意してください)

SELECT * FROM `accounting` WHERE type='cash' AND status='pending'
Response on 5.7: (Query took 0.0427 seconds.)
Response on 8.0 dev db: (Query took 0.7911 seconds.)
Response on 8.0 prod db: (Query took 4.1671 seconds.)

これらの応答時間の最初の桁は常に一貫しています。私は基礎となるハードドライブをスピードテストしました、そしてそれは古いサーバーでより速くテストしています。

グーグル中に出てきたすべての設定オプションを試してみましたが、どれもそれほど役立ちません。これが私が持っているものです。私はこれらのオプションのほとんどの大小のバージョンを試しました。このサーバーでは他に何も発生しておらず、このサイトでは現在本番環境で使用されていないため、必要なだけ実験して再起動できます。

join_buffer_size=512K
sort_buffer_size = 4M
innodb_buffer_pool_size = 5G
innodb_buffer_pool_instances=5
innodb_io_capacity = 2000
innodb_read_io_threads = 64
innodb_thread_concurrency = 16
innodb_write_io_threads = 64
innodb_log_file_size = 3G
innodb_log_buffer_size = 64M
innodb_lru_scan_depth=100
#optimizer_switch='derived_merge=off' #this significantly hurts performance
join_buffer_size=8M
tmp_table_size = 256M
max_heap_table_size=256M
table_open_cache=4000
performance_schema=OFF #roughly 25% speed increase
skip-log-bin
sync_binlog=0
innodb_flush_log_at_trx_commit=0

私はここで本当に途方に暮れています。任意の助けいただければ幸いです。

編集:私はprod-8.0 dbにtype + statusインデックスを追加しようとしましたが、速度は驚異的でした。インデックスを削除すると、dev-8.0 dbと一貫した速度が得られます。これが私たちに何を伝えているのかわかりません。

編集2:私がテストしているテーブルはMyISAMです。

更新(および解決策):

私はmariadbをインストールしてしまい、クエリは非常に高速です。 MySQLトレインから降りるときがきたと思います。

1
Talik Eichinger

成長するクエリプランナーの狂気heisenbugへようこそ。それは5.7で始まり、8.0で悪化しました。そのクエリのEXPLAINが5.7と8.0の間で著しく異なっているように見えるのは私が疑うことです。

オプションは次のとおりです。

1)optimizer_%変数を5.7と同じ値に変更すると、正常性が回復するかどうかを確認します

2)_ANALYZE TABLE accounting;_を繰り返し実行し、気が変わることを願います。統計推定はバックグラウンドで定期的に実行されるため、これは変更される可能性があることに注意してください。

3)インデックスヒントを使用します(USE/FORCE INDEX(indexname))。これは安定していますが、コードベース全体でクエリをモグラしてしまいます。

4)この種のクエリプランが不安定にならないように見えるMariaDBに切り替えます。

あなたがそうするために圧倒的に正当な理由がない限り、MyISAMを使わないでください。

1
Gordan Bobic

MyISAMテーブルで書き込みが行われていると、読み取りがブロックされることがあります。クエリ(またはクエリの組み合わせ)が4秒間テーブルをロックしていたと思います。つまり、SELECTはおそらく4秒間ブロックされた後、すぐに実行されました。スローログがこれを示している可能性があります。何がオンになったの?

INDEX(type, status)(どちらの順序でも)は、現在のクエリに役立ちます。ただし、これによって閉塞が防止されるわけではありません。

MyISAMが実際の問題であり、実際の原因が不明なクエリ(またはクエリのセット)であるため、実行しているMySQLまたはMariaDBのバージョンに関係なく、問題が再発する可能性があります。

MyISAM(これはお勧めしません)を使用する場合は、MariaDBを使用することをお勧めします。 MySQLはMyISAMを削除する可能性が高く、MariaDBはそれをより長くサポートし続ける可能性があります。

1
Rick James