Priceテーブルの多数の行に対してDELETEを実行すると、DELETEは徐々に遅くなります。 15,000行を削除すると、約15秒で実行されます。 2万行には3〜4分かかります。 40,000行は15分かかり、100,000行は1時間以上実行されます。
以下のDELETE後トリガーは、使用可能な価格タイプの数で項目テーブルを更新します。これは、生産におけるそのプロセスをスピードアップするために価格を計算するときに使用されます。
どちらのテーブルもInnoDBであり、私はinnodb_buffer_pool_sizeを4Gに更新しましたが、効果はありません。
すべてのSQLステートメントがインデックスを使用していることを確認しました。 PriceテーブルにはPriceType + ItemIDインデックスがあり、ItemIDはItemsテーブルの主キーです。
残念ながら、このスキーマは別のアプリケーションによって決定されており、テーブル構造を変更することはできません。トリガーやインデックスなどを変更できます。そのアプリケーションを変更して、Itemsテーブルのカウントを直接更新することはできません。
BEGIN
DECLARE iPriceTypeA INT;
DECLARE iPriceTypeB INT;
DECLARE iPriceTypeC INT;
SET iPriceTypeA = (SELECT COUNT(*) FROM Prices WHERE PriceType='A' AND ItemID=OLD.ItemID),
iPriceTypeB = (SELECT COUNT(*) FROM Prices WHERE PriceType='B' AND ItemID=OLD.ItemID),
iPriceTypeC = (SELECT COUNT(*) FROM Prices WHERE PriceType='C' AND ItemID=OLD.ItemID);
UPDATE Items
SET PriceTypeA = iPriceTypeA,
PriceTypeB = iPriceTypeB,
PriceTypeC = iPriceTypeC,
WHERE ItemID = OLD.ItemID;
END
これは問題を引き起こすべきではないようですが、120K行を削除すると、サーバーは数時間使用できなくなります。行数が増えると、このクエリが本質的に指数的に遅くなるのはなぜですか?
編集:価格表スキーマで更新
ItemCode varchar(30)
PriceType char(1)
Method char(1)
Factor decimal(7,2)
編集:
このトリガーが原因でレコード数が増えると削除が遅くなる理由はまだわかりません。先に述べたように、トリガー呼び出しを削除すると、削除は非常に高速です。私は本当にパフォーマンスの問題の根底に行きたいと思います。
このテーブルはアプリケーションでの選択にのみ使用されるため、今のところ問題なく機能するために、私のソリューションはMyISAMに切り替えることでした。
InnoDBでは、クラッシュやその他の理由でアクションをロールバックする場合に備えて、削除された行を保持する必要があります。これはコストがかかり、ご覧のとおり、カウントを大きくするとコストが高くなる可能性があります。
プランA:小さいチャンクで削除し、各チャンクの後にCOMMIT
を削除します。 (同様に、チャンクを更新に適用する必要があります。)
プランB、C、D、... その他のヒントを見る
WHEREがない場合
いいえWHERE
?新しいテーブルを作成してからRENAME TABLE
新しいものを原子的に所定の位置にスワップします。そしてDROP TABLE
。ダウンタイムはありません。コストのかかる削除はありません。
クエリの書き換え
5.7を実行している場合は、さまざまな種類の厄介な問題に対応するためにクエリを「書き換え」できる新機能があります。 詳細なディスカッション 。 whereなしの削除をDROP
とCREATE
に変えることができます。 (これは前の提案ほどよくありません。)