0

2 億 5000 万件を超えるレコードを含むテーブルがあります。レポート サーバーは、同様の種類のクエリを使用して、定期的にそのテーブルにクエリを実行します。

SELECT
    COUNT(*),
    DATE(updated_at) AS date,
    COUNT(DISTINCT INT_FIELD) 
FROM
    TABLE_WITH_250_Million 
WHERE
    Field1 = 'value in CHAR' 
    AND field2 = 'VALUE in CHAR' 
    AND updated_at > '2012-04-27' 
    AND updated_at < '2012-04-28 00:00:00' 
GROUP BY
    Field2,
    DATE(updated_at) 
ORDER BY
    date DESC

Field1、Field2、Field3 DESC を同じ順序で含むテーブルに BTREE インデックスを作成しようとしましたが、正しい結果が得られません。

最適化の方法を教えてください。私の問題は、このレポート サーバーがクエリを実行しているコードがないため、クエリを変更できないことです。

どんな助けでも本当に感謝しています。

ありがとう


ここに私のテーブルがあります:

CREATE TABLE backup_jobs ( 
  id int(11) unsigned NOT NULL AUTO_INCREMENT, 
  backup_profile_id int(11) DEFAULT NULL, 
  state varchar(32) DEFAULT NULL, 
  limit int(11) DEFAULT NULL, 
  file_count int(11) DEFAULT NULL, 
  byte_count bigint(20) DEFAULT NULL, 
  created_at datetime DEFAULT NULL, 
  updated_at datetime DEFAULT NULL, 
  status_type varchar(32) DEFAULT NULL, 
  status_param_1 varchar(255) DEFAULT NULL, 
  status_param_2 varchar(255) DEFAULT NULL, 
  status_param_3 varchar(255) DEFAULT NULL, 
  started_at datetime DEFAULT NULL,
  PRIMARY KEY (id),
  KEY index_backup_jobs_on_state (state),
  KEY index_backup_jobs_on_backup_profile_id (backup_profile_id),
  KEY index_backup_jobs_created_at (created_at),
  KEY idx_backup_jobs_state_updated_at (state,updated_at) USING BTREE,
  KEY idx_backup_jobs_state_status_param_1_updated_at (state,status_param_1,updated_at) USING BTREE
) ENGINE=MyISAM AUTO_INCREMENT=508748682 DEFAULT CHARSET=utf8;
4

3 に答える 3

0

対象の日付範囲で2億5000万行すべてが発生したわけではないと確信しています。

問題は、日付がどこにあるかわからないため、日付チェックの性質がテーブルスキャンを強制することです。

250Mの行テーブルを週、月、四半期、または年に分割し、特定の日付範囲に必要なパーティションのみをスキャンすることをお勧めします。範囲内のパーティションをスキャンするだけで済みます。それは問題を助けるでしょう。

パーティションロードを進む場合は、MySQL DBA、できればパーティション分割に精通している人と話す必要があります。気弱な人向けではありません。

http://dev.mysql.com/doc/refman/5.1/en/partitioning.html

于 2012-04-27T15:54:35.763 に答える
0

クエリごとに、ここで主導権を握る必要があります-最小の粒度。アクティビティの頻度、フィールド 1、フィールド 2 のステータス エントリ、データがどこまでさかのぼるか、指定された SINGLE DATE で正常なエントリの数はわかりません。とは言っても、最初にクエリ条件に厳密に一致する最小の粒度に基づいてインデックスを構築します。

例: "Field1" に多数の可能な "CHAR" 値があり、"IN" 句を適用していて、Field1 がインデックスの最初にある場合、各日付と field2 値の各文字にヒットします。2 億 5000 万のレコードは、特に履歴に基づいて、多くのインデックス ページング アクティビティを強制する可能性があります。Field2 も同様です。ただし、Field2 の「Group By」句と更新された日付により、インデックスの最初/2 番目の位置にそれぞれ 1 つがあります。過去のデータに基づいて、私は以下のインデックスを一次基準として日付を取得し、その中に二次基準を設定する傾向さえあります.

インデックス ( Updated_At、Field2、Field1、INT_FIELD )

このように、クエリ全体をインデックスだけで実行でき、実際のレコードの生データに対してクエリを実行する必要はありません。すべてのフィールドは、プル元のインデックスにあります。日付範囲が限られているため、updated_at はすぐに修飾され、group by の順序で準備されます。それから、Field2 からの「CHAR」値は、グループ化を適切に終了します。「IN」文字リストの 3 番目の基準を修飾する Field1、最後に count( distinct ) の INT_FIELD を修飾します。

インデックスが 2 億 5000 万を構築するのにどれくらいの時間がかかるかはわかりませんが、そこから始めます。

于 2012-04-27T23:57:22.730 に答える
0

int_fieldをインデックスに追加します。

CREATE INDEX idx_backup_jobs_state_status_param_1_updated_at_backup_profile_id ON backup_jobs (state, status_param_1, updated_at, backup_profile_id)

すべての分野を網羅するように。

このようにして、テーブルのルックアップが行われ (Using indexプランに表示されます)、クエリがいくらか10x高速になります (マイレージは異なる場合があります)。

また、(少なくとも提供された単一の日付範囲では)GROUP BY DATE(updated_at)andORDER BY date DESCは冗長であり、実際の目的なしに使用するクエリのみを作成することにtemporary注意filesortしてください。ただし、クエリを変更できない場合は、それについて多くのことができるわけではありません。

于 2012-04-27T16:12:29.407 に答える