2
  1. クエリの実行に時間がかかりすぎて、約 130 分かかります。
  2. テーブルにはインデックスがありますが、クエリはインデックスを使用していません。
  3. テーブルのサイズは約 3,000 万レコードです。
  4. (または)、(および) 条件を変更して、クエリを書き直すのを手伝ってください。
  5. クエリは通常の実行では使用されていないため、強制インデックスで試しましたが、うまくいきませんでした。

クエリ:

SELECT customer_history.customer_id,
        customer_history.row_mod,
        customer_history.row_create,
        customer_history.event_id,
        customer_history.event_type,
        customer_history.new_value,
        customer_history.old_value
FROM customer_history FORCE INDEX (customer_history_n2)
WHERE customer_id >= 1
        AND customer_id < 5000000
        AND (customer_history.row_mod >= '2012-10-01')
        OR (
                customer_history.row_create >= '2012-10-01'
                AND customer_history.row_create < '2012-10-13'
                );


Table structure

    CREATE TABLE `customer_history` (
      `customer_id` int(11) NOT NULL,
      `row_mod` datetime DEFAULT NULL,
      `row_create` datetime DEFAULT NULL,
      `event_id` int(11) DEFAULT NULL,
      `event_type` varchar(45) DEFAULT NULL,
      `new_value` varchar(255) DEFAULT NULL,
      `old_value` varchar(255) DEFAULT NULL,
      KEY `customer_id1` (`customer_id`),
      KEY `new_value_n1` (`new_value`),
      KEY `customer_history_n1` (`row_create`),
      KEY `customer_history_n2` (`row_mod`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8

プランの説明:

+----+-------------+------------------+------+---------------------+------+---------+------+----------+-------------+
| id | select_type | table            | type | possible_keys       | key  | key_len | ref  | rows     | Extra       |
+----+-------------+------------------+------+---------------------+------+---------+------+----------+-------------+
|  1 | SIMPLE      | customer_history | ALL  | customer_history_n2 | NULL | NULL    | NULL | 18490530 | Using where |
+----+-------------+------------------+------+---------------------+------+---------+------+----------+-------------+
1 row in set (0
4

2 に答える 2

1

このクエリを2つの部分に分割してみることができます。

SELECT customer_history.customer_id,
        customer_history.row_mod,
        customer_history.row_create,
        customer_history.event_id,
        customer_history.event_type,
        customer_history.new_value,
        customer_history.old_value
FROM customer_history
WHERE customer_id >= 1
        AND customer_id < 5000000
        AND (customer_history.row_mod >= '2012-10-01')

SELECT customer_history.customer_id,
        customer_history.row_mod,
        customer_history.row_create,
        customer_history.event_id,
        customer_history.event_type,
        customer_history.new_value,
        customer_history.old_value
FROM customer_history
WHERE  customer_history.row_create >= '2012-10-01'
       AND customer_history.row_create < '2012-10-13';

そして、それらのどれが実行と最適化に時間がかかっているかを確認します。最初のクエリと同じ結果セットを取得するにはUNION、MySQLでこれら2つのクエリを取得するか、アプリケーション層から個別に実行して結果セットを結合します。

于 2012-12-28T05:33:39.160 に答える
1

ああ、私はあなたの問題が何であるかを知っていると思います。MySQLのドキュメントによると:

USE INDEX(index_list)を指定することにより、名前付きインデックスの1つのみを使用してテーブル内の行を検索するようにMySQLに指示できます。代替構文IGNOREINDEX(index_list)を使用して、特定の1つまたは複数のインデックスを使用しないようにMySQLに指示できます。これらのヒントは、MySQLが可能なインデックスのリストから間違ったインデックスを使用していることをEXPLAINが示している場合に役立ちます。

FORCE INDEXを使用することもできます。これは、USE INDEX(index_list)のように機能しますが、テーブルスキャンは非常にコストがかかると想定されています。つまり、テーブルスキャンは、指定されたインデックスの1つを使用してテーブル内の行を検索する方法がない場合にのみ使用されます。

つまり、FORCE INDEXを使用すると、MySQLにインデックスのみを使用しcustomer_history_n2、他の使用可能なすべてのインデックスをスキップするように指示します。クエリからFORCEINDEX句を削除するか、代わりに次のように指定して、使用可能な他の列のインデックスを使用するようにする必要があります。

SELECT customer_history.customer_id,
    customer_history.row_mod,
    customer_history.row_create,
    customer_history.event_id,
    customer_history.event_type,
    customer_history.new_value,
    customer_history.old_value
FROM customer_history
    FORCE INDEX (customer_history_n2, customer_history_n1, customer_id1)
WHERE customer_id >= 1
    AND customer_id < 5000000
    AND (customer_history.row_mod >= '2012-10-01')
    OR (
        customer_history.row_create >= '2012-10-01'
        AND customer_history.row_create < '2012-10-13' );
于 2012-12-28T05:34:01.490 に答える