このクエリ更新が正常に実行できないのはなぜですか?
P粉885562567
P粉885562567 2023-09-03 16:39:14
0
2
576
<p>customers (3000 行) とphone_call_log (350,000 行) の 2 つのテーブルがあります。 </p> <p>通話ログを使用して各顧客への最後の通話時刻を実装する必要があります (フロントエンド検索の方が高速です)。 </p> <p>インデックスは次のとおりです。</p>
    <li>start_time (タイムスタンプ)</li> <li>call(bigint(32) unsigned)</li> <li>Caller(bigint(32) unsigned)</li> <li>電話番号 (bigint(32) unsigned)</li> <li>last_call(タイムスタンプ)</li> </ul> <p>このクエリを実行すると、呼び出し元/呼び出し先の列の完了時間は OR ステートメントを使用しない場合は 2 秒未満ですが、OR ステートメントを使用すると完了しません (テストでは、実行させませんでした) 30分以上)。 </p> <pre class="brush:sql;toolbar:false;">顧客を更新する SET Customers.last_call = ( SELECT max(phone_call_log.start_time) 電話の通話記録から WHERE Phone_call_log.callee = 顧客.電話番号 または、phone_call_log.caller = 顧客.電話番号 ) WHERE 顧客.電話番号が NULL ではない AND 長さ(顧客.電話番号) > 6 かつ顧客の電話番号 > 1000000; </pre></p>
P粉885562567
P粉885562567

全員に返信(2)
P粉009186469

最速

電話がかかってきたら、データ フローを変更して customers.last_call を更新します。

接続の更新

UPDATEJOIN と比較すると、IN (SELECT ...) の方が効果的です。

######または######

OR はパフォーマンスを低下させます。このクエリでは、各顧客の

phone_call_log

全体をスキャンする可能性が高くなります。 回避策の 1 つは、UPDATE を 2 回実行し、適切なインデックスを使用することです:

リーリー

これには、phone_call_log に次のインデックスを作成する必要があります:

リーリー

And現在の単一列インデックスの呼び出し元と呼び出し先を削除します。

データの種類

電話番号の場合、特に LENGTH(customers.phonenumber) > 6 を考慮すると、

BIGINT

の使用は間違っている可能性があります。 実際には、これらすべては簡単なテストに要約されます: リーリー すべての

>

チェックでは

NOT NULL

がチェックされ、データ型に応じてそのうちの 1 つだけが使用され、インデックスが付けられます。 (SHOW CREATE TABLE を入力してください。「英語」では正確さが不十分です。)

いいねを押す +0
P粉354602955

OR を使用したクエリでは、インデックスを効果的に使用できません。次のことを試してみることをお勧めします:

リーリー

#GREATEST には NULL 値の処理に問題があることに注意してください。

いいねを押す +0
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート