web-dev-qa-db-ja.com

MySQL-ラージテーブルのベストプラクティス/インデックス

現在約3300万行のデータを含むテーブルがあり、1秒ごとに常により多くの行を記録しています。このテーブルからデータをプルするクエリは、徐々に遅くなり、実際には使用できなくなります。

私のテーブルスキーマは次のようになります。

enter image description here

テーブルには次のインデックスがあります。

enter image description here

このテーブルからの通常のクエリは、シフトがXに等しく、タイムスタンプがXとYの間の行を選択することで構成されます。

誰でもより良いテーブル設定を提供/提案できますか、またはこのテーブルをより効率的にするためにインデックスをどのように改善できますか?

現在、インデックスを断片化していると思い、MySQLが接続を失い続けているため、テーブルのインデックスを再作成しようとしています。だから、どうすればこれを達成できるのかわかりません。私の考えは、テーブル構造を再作成してから、より効率的なインデックスセットを使用してデータを徐々に移行することです。

3
Phil

直接的な答えとして、クエリに必要なのは(shift、timestamp)の複合インデックスです:ALTER TABLE historical_data ADD INDEX shift_ts(shift, timestamp)

ただし、インデックスがたくさんあります。いくつかは冗長です。

  • tag_id:カーディナリティが低い。 「WHERE tag_id=x」クエリがない場合は削除してください
  • shift, timestamp:それらを1つのインデックスに結合します(これはクエリに役立ちます)
  • hd_multicolumn:ドロップ
  • value:照会しない場合は、ドロップしてください
  • hd_multicolumn2:落とす
  • [重要]テーブルがInnoDBテーブルの場合、自動インクリメントフィールドを追加し、それを主キーにします
1
Jehad Keriaki

「シフトはXに等しく、タイムスタンプはXとYの間にあります」-これがメインクエリである場合、これをお勧めします。

_id INT UNSIGNED AUTO_INCREMENT NOT NULL  -- make it `BIGINT` if expect > 4 billion
PRIMARY KEY(shift, timestamp, id)  -- In this order
INDEX(id),     -- for AUTO_INCREMENT
INDEX(shift)   -- DROP; it is now redundant with new PK
INDEX(tag_id)  -- get rid of this; it is redundant with the next two
INDEX(tag_id, shift, timestamp)  -- what query is this for?
INDEX(tag_id, timestamp)  -- what query is this for?
_

この

  • InnoDBテーブルのPKの必要性を満たし、
  • クエリに最適なインデックス_(shift, timestamp)_を提供します。
  • 効率を上げるために、そのインデックスをPKとして配置します。
  • idを追加して一意にします。
  • INDEX(id)は_AUTO_INCREMENT_を幸せに保ちます。

他に重要なクエリがある場合は、それらを確認する必要があります。それ以外の場合、この改善によりクエリに大きな悪影響が及ぶ可能性があります。

shiftはどのような値ですか? 「小さい」数値の場合は、_TINYINT UNSIGNED_または4バイトINTより小さい何かを使用してスペースを節約します。

縮小できる列が他にある場合は、それらも同時に実行しましょう。そして、必要になるかもしれない他のものを修正します。 _SHOW CREATE TABLE_を入力してください。 _utf8_は、世界のほとんどを処理しますが、中国語のすべて、またはほとんどの絵文字を処理しません。たぶん、今あなたも_utf8mb4_にシフトする必要があります。

これを変更すると、かなりのダウンタイムが発生します。また、一意のキーがないと、pt-online-schema-changeを使用できません。したがって、停止を計画します。ただし、新しいデータを引き続き受信する必要がある場合は、次の点を考慮してください。

_CREATE TABLE h_new LIKE historical_data;  -- copy schema
ALTER TABLE  h_new ... -- to get PK, better datatypes, indexes, etc.
RENAME TABLE historical_data TO h_old,
             h_new TO historical_data;  -- atomically swap
then...
_

_h_old_データを_historical_data_にチャンクごとにコピーします。方法の概要については、 chunking を参照してくださいそれをするために。注:テーブルをウォークスルーする場合はtimestampを使用する必要があります。テーブルが一意またはPKでないことを心配する必要はありません。 (そしてDELETEから_INSERT ... SELECT..._に変更します。)

すべてのチャンクが終了したら、_DROP TABLE h_old_。

1
Rick James