PHPスクリプトには、最適化が非常に必要なクレイジーなSQLクエリがいくつかあります。ただし、問題はそれらを最適化する方法ではありません。
これらのクエリには、多くの「結合」といくつかの奇妙な「順序付け」があり、数万のレコードを持つテーブルに対して実行されます。 lots_of_joins + crazy_order_byを使用すると、「tmpテーブルにコピー」ステップが必要になります。
奇妙なことに、まったく同じクエリが高速に実行されることもあり(1秒未満)、時間がかかることもあります(数十秒)。どちらの場合も、「explain」とプロファイルは「copy totmptable」ステップを示しています。クエリに時間がかかると、99%の時間が「tmpテーブルへのコピー」フェーズに費やされます。奇妙なことは、その間、mysqlはほぼ100%のCPUを消費するということです。
したがって、tmpテーブルがメモリに保持されることもあれば、ディスクに書き込まれることもあることを理解しています(現在のメモリの可用性によって異なります)。つまり、同じクエリが高速で時間がかかる場合がある理由を完全に説明できます。しかし、私にはわからないことが2つあります。
ボトルネックが一時テーブルをディスクに書き込むことである場合、それはI/Oに多くの時間を費やすことを意味するはずですが、その間の平均CPU負荷は比較的低く、確かに100%からはほど遠いはずです。大量のI/Oを実行するときに、CPUがどのようにビジーになるのでしょうか。
My.cnfで増加しました:
max_heap_table_size = 1024M
tmp_table_size = 1024M
(デフォルトは16Mだったと思います)
tmpテーブルがそれ以上のRAMを必要としているとは本当に思いません。
私の知る限り、tmpテーブルはメモリではなくディスクに書き込まれます。a-クエリとテーブルが特定の基準を満たさないためにそれを必要とする場合b-max_heap_table_sizeとtmp_table_sizeの間の最小値を超える場合
(a)が当てはまる場合、それは起こります常に、時々ではありません。一方、上記のパラメータを目立った変更なしに大幅に増やしたため、(b)である可能性は低いように思われます。必要なテーブルのサイズは、同じクエリの発生間であまり変化しないはずです(データはほぼ同じです)。したがって、メモリサイズを増やす前に、たまに発生した場合(必要なtmpテーブルのサイズがほぼ最大であったことを意味します)、このような大幅な増加の後、不安定な動作は完全に消えたはずです。
だから私の質問は基本的に:
Tmp-tableへのコピーの手順に非常に時間がかかる原因は、ディスクテーブルの作成だけですか? (または、メモリ内で実行されたとしても、時間がかかる可能性がありますか?その場合、その理由と理由はランダムですか?)
もしそうなら、
クエリの例とプロファイルは本当に必要だとは思いませんが、必要な場合は投稿できます。
Tmp_table_sizeの問題は、query_cacheを介して「醜い」クエリ(結果セット)をキャッシュすることの問題ほどではないと思います。クエリのタイプがSELECTの場合は、SQL_NO_CACHEを使用します。キャッシュされると、高速に機能しますが、キャッシュが過負荷になる可能性があり、mysqlには内部でのキャッシュの再編成に関する既知の問題がありました。また、EXPLAINを使用してクエリを確認し、必要に応じて結合に強制インデックスを使用します。
これはコメントとしてより適切ですが、私の現在の担当者は低すぎます。