4

購入したアイテムの数に基づいてすべての顧客を「ビンに入れ」、各ビンの数を表示しようとしています。何人 (account_id) が 1 つのアイテムを購入したか、2 つのアイテムを購入した人の数、9 つのアイテム、そして 10 以上のアイテムを購入したかを確認しようとしています。

これが私が使用しているクエリです - その価値のために、結果を生成するためにクエリが売上に対してフルテーブルスキャンを実行することを期待していますが、プロセス全体が永遠にかかります!

私は Oracle のバックグラウンドを持っており、Oracle の場合と同じようにクエリを作成しました。

 select  thecnt
      ,  count(*) 
   from  (select  count(*)
               ,  case when count(*) >= 10 then 'tenormore' else cast(count(*) as char) end thecnt
            from  sales
           where  created >= SUBDATE( CURRENT_DATE(), INTERVAL 60 DAY )
        group by  account_id) sub
group by  thecnt
order by  thecnt;

サブクエリを処理するときに mysql に落とし穴はありますか?

計画を説明する

+----+-------------+-------------------+-------+---------------+---------+---------+------+---------+----------+-----------------------------------------------------------+
| id | select_type | table             | type  | possible_keys | key     | key_len | ref  |     rows    | filtered | Extra                                                     |
+----+-------------+-------------------+-------+---------------+---------+---------+------+---------+----------+-----------------------------------------------------------+
|  1 | PRIMARY     | <derived2>        | ALL   | NULL          | NULL    | NULL    | NULL | 2143248 |   100.00 | Using temporary; Using filesort                           |
|  2 | DERIVED     | sales             | range | created       | created | 8       | NULL | 2012492 |   100.00 | Using where; Using index; Using temporary; Using filesort |
+----+-------------+-------------------+-------+---------------+---------+---------+------+---------+----------+-----------------------------------------------------------+
2 rows in set, 1 warning (1 hour 4 min 6.14 sec)


mysql> describe sales;
+-----------------+---------------------+------+-----+---------+-------+
| Field           | Type                | Null | Key | Default | Extra |
+-----------------+---------------------+------+-----+---------+-------+
| account_id      | char(36)            | NO   | PRI | NULL    |       |
| created         | datetime            | NO   | MUL | NULL    |       |
| histogram_value | bigint(20) unsigned | NO   | PRI | NULL    |       |
+-----------------+---------------------+------+-----+---------+-------+
4

3 に答える 3

1

適切なインデックスが欠落している可能性があります。

編集:

サブクエリの結果がメモリに収まらず、ディスク上の一時テーブルが使用されているため、クエリが遅くなります。

したがって、(account_id、created)のインデックスを使用すると、サブクエリにディスク上のtmpテーブルを使用できなくなります。

ALTER TABLE sales ADD INDEX ix_acc_cre (account_id, created)
于 2010-08-27T22:37:29.423 に答える
1

クエリに特に問題はありません。クエリが遅い理由は、一時テーブルとファイルソートを使用する必要があるためです。このクエリを大幅に高速化する唯一の方法は、MySQL 設定を変更してより多くのメモリを割り当て、これらのプロセスにディスクを使用しないようにすることです。これは、関連する設定をカバーする記事のスポットです。


編集:これを行うと、他の人が言及したように、の代わりにカウントする正確な列を指定しCOUNT(*)たり、その他のいくつかのマイナーな調整を行ったりすることで、メモリを節約することもできます。メモリを最大限に活用するために、必要なだけ小さいデータ セットを取得する必要があります。しかし、より多くのメモリを割り当てない限り、全体的な問題は解決しないと思います。

于 2010-08-28T01:44:56.240 に答える
0

MySQL が実際の行を調べる代わりにインデックスからデータを抽出できる場合、インデックスはフル テーブル スキャンで役立ちます。ここではサブクエリは必要ありません。

SELECT COUNT(account_id) AS thecnt, 
     IF(COUNT(account_id) < 10, COUNT(account_id), 'tenormore')
   FROM sales
     WHERE created >= SUBDATE( CURRENT_DATE(), INTERVAL 60 DAY )
   GROUP BY account_id 
   ORDER BY thecnt DESC

お役に立てれば。

于 2010-08-28T03:24:46.633 に答える