現在約3300万行のデータを含むテーブルがあり、1秒ごとに常により多くの行を記録しています。このテーブルからデータをプルするクエリは、徐々に遅くなり、実際には使用できなくなります。
私のテーブルスキーマは次のようになります。
テーブルには次のインデックスがあります。
このテーブルからの通常のクエリは、シフトがXに等しく、タイムスタンプがXとYの間の行を選択することで構成されます。
誰でもより良いテーブル設定を提供/提案できますか、またはこのテーブルをより効率的にするためにインデックスをどのように改善できますか?
現在、インデックスを断片化していると思い、MySQLが接続を失い続けているため、テーブルのインデックスを再作成しようとしています。だから、どうすればこれを達成できるのかわかりません。私の考えは、テーブル構造を再作成してから、より効率的なインデックスセットを使用してデータを徐々に移行することです。
直接的な答えとして、クエリに必要なのは(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
:落とす「シフトは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?
_
この
(shift, timestamp)
_を提供します。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
_。