3

よろしくお願いします。データベースを MySQL 5.5 から 5.7 にアップグレードする際に問題が発生し、完全に困惑しました。アップグレードは mysqldump などを使用して行われたのではなく、いくつかの非常に長い SQL スクリプトを使用して、いくつかのタブで区切られた入力ファイルからの再構築として行われました。特に (ストアド プロシージャ内の) 一見無害なクエリの 1 つが問題を引き起こし、その理由がわかりません。

UPDATE liverpool.master_person mp 
SET Link_Count = ( SELECT count(*) FROM liverpool.person_record pr
WHERE mp.Master_Person_ID = pr.Master_Person_ID ) - 1;

これはかなり単純に見えますが、このクエリの EXPLAIN は、深刻な行スキャンが行われていることを示しています。

# id | select_type          | table | partitions | type    | possible_keys | key                    | key_len | ref  | rows      | filtered | Extra
========================================================================================================================================================================
'1'  | 'UPDATE'             | 'mp'  | NULL       | 'index' | NULL          | 'PRIMARY'              | '4'     | NULL | '1198100' | '100.00' | NULL
------------------------------------------------------------------------------------------------------------------------------------------------------------------------
'2'  | 'DEPENDENT SUBQUERY' | 'pr'  | NULL       | 'index' | NULL          | 'Master_Person_ID_IDX' | '17'    | NULL | '1200537' | '100.00' | 'Using where; Using index'

重要なのは行列で、UPDATE の場合は 1198100、SELECT サブクエリの場合は 1200537 のようです。これらの数値はどちらも、両方の参照テーブルの合計行数 (両方とも 1207744) にかなり近い値です。したがって、両方の行スキャンに対して完全な行を実行しているように見えますが、その理由はわかりません。MySQL 5.5 では、まったく同じクエリが正常に機能しました。この解決策が役立つことを期待していましたが、「derived_merge=off」をoptimizer_switchに渡し、サーバーを再起動しても役に立ちませんでした.

私は確かに、このクエリが超高速であるとは思っていません。そうである必要はありません。以前は正確には高速ではありませんでしたが (7200rpm の回転ディスクで数分)、MySQL 5.7 へのアップグレード以降、宇宙の熱による死の前に完了することはないように思われます。長いです。アイデアを持っている人はいますか?クエリの書き換えか、my.ini 設定か、それとも何か?

また、何らかの形でプロトコルに違反した場合、または質問を改善できる場合はお知らせください. 上にも書きましたが、初めての投稿です。

お時間をいただきありがとうございます。

編集:このソリューションは有望に見えると一瞬思いました。どうやら、文字セット/照合順序が異なるテーブルは、互いのインデックスを適切に読み取ることができません。すべてが にあると確信latin1していましたが、確認する価値があると考えました。DEFAULT CHARSET=latin1そのため、すべてのCREATE TABLEステートメントに明示的に追加しCHARACTER SET latin1、ステートメントに追加しましたLOAD DATA INFILE。悲しいことに、変化はありません。

4

1 に答える 1

2

クエリを次のように書き直してみてください。

UPDATE liverpool.master_person mp
  JOIN (SELECT Master_Person_ID, count(*) as cnt
          FROM liverpool.person_record
         GROUP BY Master_Person_ID)
       ) pr
    ON mp.Master_Person_ID = pr.Master_Person_ID
   SET mp.Link_Count = pr.cnt - 1
于 2016-09-14T08:27:27.387 に答える