7

最適化したいこの大きなクエリがあります。既に最適化していますが、それでも時間がかかる場合があります (>1 秒):

select count(DISTINCT if(ps15.specification in ('All Season'),p.products_id,NULL)) as count1 ,count(DISTINCT if(ps15.specification in ('Winter'),p.products_id,NULL)) as count2 ,count(DISTINCT if(ps15.specification in ('Zomer'),p.products_id,NULL)) as count3 ,count(DISTINCT if(ps15.specification in ('Winter 2012'),p.products_id,NULL)) as count4 ,count(DISTINCT if(ps15.specification in ('Zomer 2013'),p.products_id,NULL)) as count5 ,count(DISTINCT if(ps15.specification in ('Winter 2013'),p.products_id,NULL)) as count6 ,count(DISTINCT if(ps15.specification in ('Zomer 2014'),p.products_id,NULL)) as count7
from (products p)
inner join (products_to_categories p2c)
  on (p.products_id = p2c.products_id)
inner join (products_attributes pa)
  on (p.products_id = pa.products_id)
inner join (products_options_values pv)
  on (pa.options_values_id = pv.products_options_values_id)
inner join (products_stock ps)
  on (p.products_id=ps.products_id 
    and pv.products_options_values_id = ps.products_options_values_id2 
    and ps.products_stock_quantity>0)
INNER JOIN products_specifications ps15 
  ON p.products_id = ps15.products_id  
    AND ps15.specifications_id = '15'
    AND ps15.language_id = '1'
INNER JOIN products_specifications ps10 
  ON p.products_id = ps10.products_id  
    AND ps10.specifications_id = '10' 
    AND ps10.language_id = '1' 
where p.products_status = '1'
  and p2c.categories_id in (72,1,23,100,74,24,33,34,35,77,110,25,45,44,40,41,42,85,76,78,83,102,107,111,119,50,52,81,105,108,112,86,88,87,98,89,90,91,96,79,2,54,60,82,109,115,118,53,58,104,55,101,75,56,64,66,67,68,69,70,71,84,103,114,120,80,92,99,93,94,95,97,106,121)  
  AND ps10.specification in ('Meisje')  
  and products_options_values_name in ( 62,"3M/60cm","56-62","0-4 mnd","3m","0-3m","3-6m","3M","62/68","0-6m","50-62" , 68,"6M/67cm","9M/70cm","4-8 mnd","6m","3-6m","6M","62/68","0-6m" , 74,"4-8 mnd","8-12 mnd","6m","9m","6-9m","6M","9M","74/80","6-12m" );

出力は次のとおりです。

+--------+--------+--------+--------+--------+--------+--------+
| count1 | count2 | count3 | count4 | count5 | count6 | count7 |
+--------+--------+--------+--------+--------+--------+--------+
|      1 |    289 |    193 |     49 |    192 |    240 |      0 |
+--------+--------+--------+--------+--------+--------+--------+

mysql の出力について説明します。

+----+-------------+-------+-------+-------------------------------------------+-------------------------------------+---------+---------------------------------------+------+--------------------------+
| id | select_type | table | type  | possible_keys                             | key                                 | key_len | ref                                   | rows | Extra                    |
+----+-------------+-------+-------+-------------------------------------------+-------------------------------------+---------+---------------------------------------+------+--------------------------+
|  1 | SIMPLE      | p     | index | PRIMARY,products_id                       | products_id                         | 5       | NULL                                  | 4539 | Using where; Using index |
|  1 | SIMPLE      | p2c   | ref   | PRIMARY                                   | PRIMARY                             | 4       | kikleding.p.products_id               |    1 | Using where; Using index |
|  1 | SIMPLE      | ps15  | ref   | products_id                               | products_id                         | 12      | kikleding.p2c.products_id,const,const |    1 | Using where              |
|  1 | SIMPLE      | ps10  | ref   | products_id                               | products_id                         | 12      | kikleding.p.products_id,const,const   |    1 | Using where              |
|  1 | SIMPLE      | pa    | ref   | idx_products_attributes_products_id       | idx_products_attributes_products_id | 4       | kikleding.p.products_id               |    6 |                          |
|  1 | SIMPLE      | pv    | ref   | PRIMARY                                   | PRIMARY                             | 4       | kikleding.pa.options_values_id        |    2 | Using where              |
|  1 | SIMPLE      | ps    | ref   | idx_products_stock_attributes,products_id | idx_products_stock_attributes       | 4       | kikleding.ps15.products_id            |    6 | Using where              |
+----+-------------+-------+-------+-------------------------------------------+-------------------------------------+---------+---------------------------------------+------+--------------------------+

ほとんどのテーブルにインデックスを付けようとしましたが、ref は説明の最初の行で NULL を返します。

現在は 7 列を出力していますが、50 列を出力する必要がある場合もあります。

何かアドバイス?

4

1 に答える 1

3

ref = NULLonly は、pテーブルの行 (つまりproduct) が他の行に対して結合されないことを意味します。これらの行がクエリで最初に選択され、他のテーブルの行が再び結合されます。EXPLAINの最初の行が表示されることを常に期待していref = NULLます。

基本的に、実行計画は次のように述べています。

  1. 条件にproducts一致する行を抽出するWHERE
  2. 次に、フィールドproducts_to_categoriesの(1)から行に一致する行を抽出しますproducts.products_id
  3. など、すべてのテーブルで

推奨される追加インデックス:

  • テーブル(列)
  • products(product_id, products_status)
  • products_specifications(製品 ID、仕様、言語 ID、仕様 ID)
  • products_to_categories(products_id、categories_id)

最初のものは賢明に役立つはずですが、他の2つにはあまり期待しません.

問題はあなたの多くにあると思いますCOUNT(IF())。これはハックであり、エンジンはこの種のクエリに対して実際には最適化されていません。代わりに、次のような結果セットを返すことを目指す必要があります。

+------+-------+
| | 仕様 | カウント |
+------+-------+
| | オールシーズン | 1 |
+------+-------+
| | 冬 | 冬 | 289 |
+------+-------+
| | ... | ... |
+------+-------+

クエリは次のようになります。

SELECT
    specification,
    COUNT(*)
FROM products
JOIN ... -- your current JOIN list
GROUP BY specification -- this is the important bit

products_specifications(products_id, specification)...そして、追加のインデックスがなくても(またはおそらく上に)、事実上瞬時に実行されるはずです

于 2013-10-18T12:55:41.423 に答える