1
  1. 私のクエリは、出力を取得するのに約 2800 秒かかります。
  2. インデックスもありますが、運がありません。
  3. 私の目標は、2〜3秒で出力を取得する必要があります。
  4. 可能であれば、クエリを書き直してください。

    query:
     select ttl.id, ttl.url, ttl.canonical_url_id  
     from t_target_url ttl  
     where ttl.own_domain_id=476 and ttl.type != 10  
     order by ttl.week_entrances desc  
     limit 550000;
    
    Explain Plan:
    +----+-------------+-------+------+--------------------------------+---------------------------+---------+-------+----------+-----------------------------+
    | id | select_type | table | type | possible_keys                  | key                       | key_len | ref   | rows     | Extra                       |
    +----+-------------+-------+------+--------------------------------+---------------------------+---------+-------+----------+-----------------------------+
    |  1 | SIMPLE      | ttl   | ref  | own_domain_id_type_status,type | own_domain_id_type_status | 5       | const | 57871959 | Using where; Using filesort |
    +----+-------------+-------+------+--------------------------------+---------------------------+---------+-------+----------+-----------------------------+
    1 row in set (0.80 sec)
    
    
    mysql> show create table t_target_url\G
    *************************** 1. row ***************************
           Table: t_target_url
    Create Table: CREATE TABLE `t_target_url` (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `own_domain_id` int(11) DEFAULT NULL,
      `url` varchar(2000) NOT NULL,
      `create_date` datetime DEFAULT NULL,
      `friendly_name` varchar(255) DEFAULT NULL,
      `section_name_id` int(11) DEFAULT NULL,
      `type` int(11) DEFAULT NULL,
      `status` int(11) DEFAULT NULL,
      `week_entrances` int(11) DEFAULT NULL COMMENT 'last 7 days entrances',
      `week_bounces` int(11) DEFAULT NULL COMMENT 'last 7 days bounce',
      `canonical_url_id` int(11) DEFAULT NULL COMMENT 'the primary URL ID, NOT allow canonical of canonical',
      KEY `id` (`id`),
      KEY `urlindex` (`url`(255)),
      KEY `own_domain_id_type_status` (`own_domain_id`,`type`,`status`),
      KEY `canonical_url_id` (`canonical_url_id`),
      KEY `type` (`type`,`status`)
    ) ENGINE=InnoDB AUTO_INCREMENT=227984392 DEFAULT CHARSET=utf8
    /*!50100 PARTITION BY RANGE (`type`)
    (PARTITION p0 VALUES LESS THAN (0) ENGINE = InnoDB,
     PARTITION p1 VALUES LESS THAN (1) ENGINE = InnoDB,
     PARTITION p2 VALUES LESS THAN (2) ENGINE = InnoDB,
     PARTITION pEOW VALUES LESS THAN MAXVALUE ENGINE = InnoDB) */
    1 row in set (0.00 sec)
    
4

1 に答える 1

4

クエリ自体は問題ないように見えますが、句による順序であり、50万レコードの可能性がおそらくあなたのキラーです。その部分を最適化するのに役立つインデックスを追加します

(own_domain_id、week_entrances、type)

したがって、このようにして、最初に重要なキー「own_domain_id」を押してから、すべてをすでに順番に取得します。タイプは!= 10用であるため、他のタイプであり、2番目のインデックス位置にある場合はさらに問題が発生するように見えます。

コメントフィードバック。

簡単にするために、where句ごとの重要なキーは「ttl.own_domain_id=476」です。ドメインID476のデータのみを考慮します。ここで、次のようなすべての異なる週の入り口にまたがる15の「タイプ」があると仮定します。

own_domain_id   type   week_entrances
476             1      1000
476             1      1700
476             1      850
476             2      15000
476             2      4250
476             2      12000
476             7      2500
476             7      5300
476            10      1250
476            10      4100
476            12      8000
476            12      3150
476            15      5750
476            15      27000

これは明らかに50万の容量の規模ではありませんが、サンプルデータを示しています。タイプ!= 10にすることで、id = 476のすべてのレコードをブロースルーする必要がありますが、タイプ=10のレコードのみを除外する必要があります。より多くの時間。キーの一部として週の入り口を2番目の位置、次にタイプにすることにより、データは、返された結果セットですでに適切な順序で最適化できるようになります。ただし、「!= 10」のタイプになると、それらが検出されるとすぐにスキップされます。上記のサンプルごとに改訂されたインデックスデータは次のとおりです。

own_domain_id   week_entrances  type   
476             850             1
476             1000            1
476             1250            10
476             1700            1
476             2500            7
476             3150            12
476             4100            10
476             4250            2
476             5300            7
476             5750            15
476             8000            12
476             12000           2
476             15000           2
476             27000           15

したがって、ご覧のとおり、データはインデックスごとに事前に並べ替えられており、降順の適用はエンジンにとって問題ありません。レコードを逆の順序でプルし、見つかった10をスキップします。

それは役に立ちますか?

Salmanごとの追加のコメントフィードバック。

これを別の方法で考えてみてください。店舗には10の異なる支店があり、それぞれに独自の売り上げがあります。取引の領収書は(文字通り)ボックスに保存されます。特定の日付のすべてのトランザクションを探している場合、ボックスをどのように通過するかを考えてください。

Box 1 = Store #1 only, and transactions sorted by date
Box 2 = Store #2 only, and transactions sorted by date
Box ...
Box 10 = Store #10 only, sorted by date.

10個のボックスを通過し、特定の日付のすべてを引き出す必要があります...または、元の質問では、1つの日付を除くすべてのトランザクションで、日付に関係なく、トランザクションの金額順に並べたいと考えています...何可能性のある混乱。

ストアに関係なく、ボックスを事前にグループ化した場合

Box 1 = Sales from $1 - $1000 (all properly sorted by amount)
Box 2 = Sales from $1001 - $2000 (properly sorted)
Box ...
Box 10... same...

それでも、すべてのボックスを調べて整理する必要がありますが、少なくとも、トランザクションを調べているときに、日付の除外のために1つを破棄して無視することができます。

インデックスは、エンジンが基準に合わせてインデックスを最適に通過する方法を事前に整理するのに役立ちます。

于 2012-12-31T10:12:11.627 に答える