1

クエリが数秒から数時間にジャンプするまで、優れたパフォーマンスを体験しています。

A)調査B)Mysqlで大量のデータをクエリする場合の主要なパフォーマンスのボトルネックを解決するにはどうすればよいですか?

おそらくメモリ関連ですか?


結果

ストアドプロシージャのパフォーマンスをテストする際に、最初に5分以内に2回実行しました...

mysql> CALL TopFromBigTable('2012-04-01','2012-05-01',5);
5 rows in set (23.76 sec)

これは非常に高速ですが、それから私はそれをもう一度呼び出します...私は1時間以上後にそれを殺しました!

mysql> CALL TopFromBigTable('2012-04-01','2012-05-01',5);

---TRANSACTION 1484EF5C, ACTIVE 3571 sec fetching rows, thread declared inside InnoDB 193
mysql tables in use 2, locked 1
MySQL thread id 466174, OS thread handle 0x7f3616ab4700, query id 33098684 localhost    root Copying to tmp table

その他のテスト:

mysql> CALL TopFromBigTable('2012-05-01','2012-05-04',5);
5 rows in set (1.28 sec)
mysql> CALL TopFromBigTable('2012-05-01','2012-05-05',5);
5 rows in set (1.55 sec)
mysql> CALL TopFromBigTable('2012-05-01','2012-05-06',5);
5 rows in set (1 hour 47 min 37.99 sec)

詳細

テーブル

CREATE TABLE `BigTable` (
  `BigTableID` int(11) NOT NULL,
  `AnotherID` int(11) NOT NULL,
  `Type` char(2) COLLATE utf8_unicode_ci DEFAULT NULL,
  `StartTime` datetime NOT NULL,
  `EndTime` datetime DEFAULT NULL,
  PRIMARY KEY (`BigTableID`),
  KEY `Type` (`Type`),
  KEY `StartTime` (`StartTime`),
  KEY `EndTime` (`EndTime`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci

クエリ(このジェネリックを作成する際に私がgroup by間違っていたことに注意してください)

CREATE PROCEDURE `TopFromBigTable` (
    $StartDate DATETIME,
    $EndDate DATETIME,
    $ResultLimit INT
    )
BEGIN

    SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED ;
    SELECT
        `Type`,
        COUNT(*) AS Count
    FROM
        `BigTable`
    WHERE                
            `StartTime` > $StartDate
        AND
            `StartTime` < $EndDate
    GROUP BY
        `Type`
    ORDER BY
        Count DESC
    LIMIT $ResultLimit
    ;
    COMMIT;

END $$

実行計画

EXPLAIN EXTENDED ...
           id: 1
  select_type: SIMPLE
        table: BigTable
         type: range
possible_keys: StartTime
          key: StartTime
      key_len: 8
          ref: NULL
         rows: 16446226
     filtered: 100.00
        Extra: Using where; Using temporary; Using filesort

私は専用のレポートデータベースで実行しているため、すべての通常のルールが適用されるわけではありません。つまり、精度は重要ではなく、このデータベースは過去6時間に更新されなかったため、オーバーヘッドを削減するためにコミットされていない読み取りを行いました。これが実際にどれだけ役立つかをベンチマークしたいのですが(仮にあったとしても)、ストアドプロシージャの時間を確実に計ることはできません!

4

3 に答える 3

1

これは難しいものです...本当に大きなテーブルの場合 - StartTime に追加してインデックスを作成するには時間がかかり、余分なスペースが少し必要になる場合がありますが、http://devに従って USE INDEX を指定すると、選択速度が向上します.mysql.com/doc/refman/5.1/en/index-hints.html

毎日挿入される行数に応じて、必ずインデックスを再作成してください...それについてはあなたの裁量を使用してください。

あなたの興味深い問題を調査しているときに、私もこれに出くわしました: http://www.petefreitag.com/item/613.cfm

于 2012-05-28T22:13:00.430 に答える
0

Type100K の値ではなく、少数 (50) の個別の値しか持たないことによってグループ化するため、2 つのオプションが表示されます。

  • 複合(Type, StartTime)インデックス。

インデックスはクエリを「カバー」しています。つまり、クエリはインデックスのみを使用し、テーブルにはまったくヒットしません。それでも index の大部分をスキャンし、 ごとTypeに項目をカウントする必要があるため、期待できる最善の方法ではありませんがType、テーブルに 50 個の値しかないため、うまく機能すると思います。(最終的なファイルソート - わずか 50 行 - は問題になりません。)

  • このクエリのもう 1 つのカバー インデックスは、複合(StartTime, Type)です。

クエリがこれを使用する場合、インデックスの一部からすべてのデータを読み取るため、場合によっては高速になる可能性があります (開始時間ウィンドウが小さく、Typeより多くの異なる値がある場合)。しかし、group byTypeを使用すると、特に大きなウィンドウでは、おそらく最初のものよりもパフォーマンスが低下します。

上記のインデックスとさまざまなパラメーターの両方をテスト/実験するのが最善だと思います。

于 2012-05-30T22:26:46.123 に答える
0

詳細な回答。

  1. ストアド プロシージャをサンプル クエリに分割する
  2. 使用するEXPLAIN EXTENDED
  3. EXPLAIN EXTENDEDオプティマイザが計画を変更する可能性があるため、さまざまな入力を使用してください。

ランダムな動作は、オプティマイザがテーブルの統計を異なる方法で計算し (時間をかけてバックグラウンドで計算します)、効果の低いインデックスを選択することでした。解決策は、ヒントを使用してより良いインデックスを強制するUSE INDEX(StartTime)か、インデックスを調整することです。

わかった

EXPLAIN EXTENDED
SELECT
    `Type`,
    COUNT(*) AS Count
FROM
    `BigTable`
WHERE                
        (`StartTime` > '2012-02-01')  
    AND
        (`StartTime` < '2012-02-02' ) 
GROUP BY
    `Type`
ORDER BY
    Count DESC
LIMIT 5
;

           id: 1
  select_type: SIMPLE
        table: BigTable
         type: range
possible_keys: StartTime
          key: StartTime
      key_len: 8
          ref: NULL
         rows: 170986
     filtered: 100.00
        Extra: Using where; Using temporary; Using filesort

悪い (不適切なインデックス、3,800 万行、15% のフィルター処理)

EXPLAIN EXTENDED
SELECT
    `Type`,
    COUNT(*) AS Count
FROM
    `BigTable`
WHERE                
        (`StartTime` > '2012-02-01')  
    AND
        (`StartTime` < '2012-03-01' ) 
GROUP BY
    `Type`
ORDER BY
    Count DESC
LIMIT 5
;
           id: 1
  select_type: SIMPLE
        table: BigTable
         type: index
possible_keys: StartTime
          key: Type
      key_len: 7
          ref: NULL
         rows: 38311434
     filtered: 14.54
        Extra: Using where; Using temporary; Using filesort

固定 (5M 行)

EXPLAIN EXTENDED
SELECT
    `Type`,
    COUNT(*) AS Count
FROM
    `BigTable`
    USE INDEX (`StartTime`)
WHERE                
        (`StartTime` > '2012-02-01')  
    AND
        (`StartTime` < '2012-02-02' ) 
GROUP BY
    `Type`
ORDER BY
    Count DESC
LIMIT 5
;

           id: 1
  select_type: SIMPLE
        table: BigTable
         type: range
possible_keys: StartTime
          key: StartTime
      key_len: 8
          ref: NULL
         rows: 5572320
     filtered: 100.00
        Extra: Using where; Using temporary; Using filesort
于 2012-05-30T22:20:13.540 に答える