使用OrderBy MySQL非常慢

时间:2012-05-29 11:12:47

标签: mysql sql-order-by

在应用OrderBy时,我的一个查询运行速度非常慢,我遇到了问题。

我已经浏览过并使用SELECT * FROM(sql stuff)OrderBy字段包围我的查询。这将时间从22秒减少到10秒,但我真的需要更快。 SQL_NO_CACHE仅用于测试。

这将在10秒内返回5866条记录。删除orderby会在2秒后返回。

SELECT 
     SQL_NO_CACHE * 
FROM
     (SELECT 
          SUM(
               MATCH(product_name) 
               AGAINST ('"Jeans"' IN BOOLEAN MODE) + 
               MATCH(store_name) 
               AGAINST ('"Jeans"' IN BOOLEAN MODE)
          ) AS searchScore,
          product_name,
          section_url,
          product_link_url,
          affiliate_store_product_id,
          store_url,
          product_date_added,
          product_image,
          product_image_path,
          product_sale_price,
          product_price,
          product_price_currency,
          product_url,
          product_id,
          product_channel_id,
          store_name,
          product_brand,
          colour_id,
          colour_name 
     FROM
          products 
          INNER JOIN stores 
               ON store_id = product_store_id 
          LEFT OUTER JOIN product_colours 
               ON product_colour_product_id = product_id 
          LEFT OUTER JOIN colours 
               ON colour_id = product_colour_colour_id 
          LEFT OUTER JOIN sections 
               ON product_channel_id = section_id 
          INNER JOIN storeShipping 
               ON storeShipping_store_id = store_id 
          INNER JOIN shipping_locations 
               ON shipping_location_id = storeShipping_shipping_location_id 
          JOIN product_categories 
               ON product_category_product_id = product_id 
          JOIN categories 
               ON category_id = product_category_category_id 
     WHERE (
               MATCH(product_name) AGAINST ('"Jeans"' IN BOOLEAN MODE) 
               OR MATCH(store_name) AGAINST ('"Jeans"' IN BOOLEAN MODE)
          ) 
          AND product_status = 1 
          AND category_status = 1 
          AND product_excluded = 0 
          AND product_feed_status = 1 
          AND store_status = 1 
          AND shipping_location_currency_code = 'AUD' 
          AND product_image_path IS NOT NULL 
          AND (
               product_channel_id = 1 
               OR product_channel_id = 2 
               OR product_channel_id = 3 
               OR product_channel_id = 4
          ) 
     GROUP BY product_url) AS T 
ORDER BY searchScore DESC ;

以下是orderby

的解释
+----+-------------+--------------------+--------+---------------------------------------------------------------------------------------------------------------------------+------------------------+---------+--------------------------------------------------+--------+----------------------------------------------+
| id | select_type |       table        |  type  |                                                       possible_keys                                                       |          key           | key_len |                       ref                        |  rows  |                    Extra                     |
+----+-------------+--------------------+--------+---------------------------------------------------------------------------------------------------------------------------+------------------------+---------+--------------------------------------------------+--------+----------------------------------------------+
|  1 | PRIMARY     | <derived2>         | ALL    | \N                                                                                                                        | \N                     | \N      | \N                                               |   5866 | Using filesort                               |
|  2 | DERIVED     | products           | ref    | PRIMARY,idx_product,idx_channel,idx_path,idx_store,idx_excluded,idx_status,idx_product_feed_status,idx_product_image_path | idx_status             | 2       |                                                  | 306688 | Using where; Using temporary; Using filesort |
|  2 | DERIVED     | stores             | eq_ref | PRIMARY,idx_storestatus                                                                                                   | PRIMARY                | 4       | products.product_store_id                        |      1 | Using where                                  |
|  2 | DERIVED     | product_categories | ref    | PRIMARY,idx_category,idx_categoryproduct                                                                                  | idx_categoryproduct    | 4       | products.product_id                              |      1 |                                              |
|  2 | DERIVED     | categories         | eq_ref | PRIMARY,NewIndex1                                                                                                         | PRIMARY                | 4       | product_categories.product_category_category_id  |      1 | Using where                                  |
|  2 | DERIVED     | product_colours    | ref    | idx_colourproduct                                                                                                         | idx_colourproduct      | 5       | products.product_id                              |      2 |                                              |
|  2 | DERIVED     | colours            | eq_ref | PRIMARY                                                                                                                   | PRIMARY                | 4       | product_colours.product_colour_colour_id         |      1 |                                              |
|  2 | DERIVED     | storeShipping      | ref    | idx_storeshippingstore,idx_storeshippinglocation                                                                          | idx_storeshippingstore | 5       | stores.store_id                                  |      4 | Using where                                  |
|  2 | DERIVED     | shipping_locations | eq_ref | PRIMARY,idx_shippinglocation                                                                                              | PRIMARY                | 4       | storeShipping.storeShipping_shipping_location_id |      1 | Using where                                  |
|  2 | DERIVED     | sections           | eq_ref | PRIMARY                                                                                                                   | PRIMARY                | 4       | products.product_channel_id                      |      1 |                                              |
+----+-------------+--------------------+--------+---------------------------------------------------------------------------------------------------------------------------+------------------------+---------+--------------------------------------------------+--------+----------------------------------------------+

没有orderby

+--------+-------------+--------------------+--------+---------------------------------------------------------------------------------------------------------------------------+------------------------+---------+--------------------------------------------------+--------+----------------------------------------------+
|     id | select_type |       table        |  type  |                                                       possible_keys                                                       |          key           | key_len |                       ref                        |  rows  |                    Extra                     |
+--------+-------------+--------------------+--------+---------------------------------------------------------------------------------------------------------------------------+------------------------+---------+--------------------------------------------------+--------+----------------------------------------------+
|      1 | SIMPLE      | products           | ref    | PRIMARY,idx_product,idx_channel,idx_path,idx_store,idx_excluded,idx_status,idx_product_feed_status,idx_product_image_path | idx_status             |       2 | const                                            | 306688 | Using where; Using temporary; Using filesort |
|      1 | SIMPLE      | stores             | eq_ref | PRIMARY,idx_storestatus                                                                                                   | PRIMARY                |       4 | products.product_store_id                        |      1 | Using where                                  |
|      1 | SIMPLE      | product_categories | ref    | PRIMARY,idx_category,idx_categoryproduct                                                                                  | idx_categoryproduct    |       4 | products.product_id                              |      1 |                                              |
|      1 | SIMPLE      | categories         | eq_ref | PRIMARY,NewIndex1                                                                                                         | PRIMARY                |       4 | product_categories.product_category_category_id  |      1 | Using where                                  |
|      1 | SIMPLE      | product_colours    | ref    | idx_colourproduct                                                                                                         | idx_colourproduct      |       5 | products.product_id                              |      2 |                                              |
|      1 | SIMPLE      | colours            | eq_ref | PRIMARY                                                                                                                   | PRIMARY                |       4 | product_colours.product_colour_colour_id         |      1 |                                              |
|      1 | SIMPLE      | storeShipping      | ref    | idx_storeshippingstore,idx_storeshippinglocation                                                                          | idx_storeshippingstore |       5 | stores.store_id                                  |      4 | Using where                                  |
|      1 | SIMPLE      | shipping_locations | eq_ref | PRIMARY,idx_shippinglocation                                                                                              | PRIMARY                |       4 | storeShipping.storeShipping_shipping_location_id |      1 | Using where                                  |
|      1 | SIMPLE      | sections           | eq_ref | PRIMARY                                                                                                                   | PRIMARY                |       4 | products.product_channel_id                      |      1 |                                              |
+--------+-------------+--------------------+--------+---------------------------------------------------------------------------------------------------------------------------+------------------------+---------+--------------------------------------------------+--------+----------------------------------------------+

你们可以做些什么来给我一个提升力量很棒!

谢谢!

2 个答案:

答案 0 :(得分:0)

我稍微修改了你的查询。你能试试吗? 另请INDEXproduct_url这将大大提高执行力。 如果可能INDEXproduct_namestore_name

SELECT SUM(CASE WHEN product_name LIKE '%Jeans%' OR store_name LIKE '%Jeans%' 
                THEN 1 
           ELSE 0 END) AS searchScore,
       product_name, 
       section_url, 
       product_link_url, 
       affiliate_store_product_id, 
       store_url, 
       product_date_added, 
       product_image, 
       product_image_path, 
       product_sale_price, 
       product_price, 
       product_price_currency, 
       product_url, 
       product_id, 
       product_channel_id, 
       store_name, 
       product_brand, 
       colour_id, 
       colour_name 
FROM products 
             INNER JOIN stores ON store_id = product_store_id 
             LEFT OUTER JOIN product_colours ON product_colour_product_id = product_id 
             LEFT OUTER JOIN colours ON colour_id = product_colour_colour_id 
             LEFT OUTER JOIN sections ON product_channel_id = section_id 
             INNER JOIN storeShipping ON storeShipping_store_id = store_id 
             INNER JOIN shipping_locations ON shipping_location_id = storeShipping_shipping_location_id 
             JOIN product_categories ON product_category_product_id = product_id 
             JOIN categories ON category_id = product_category_category_id 
WHERE (product_name LIKE '%Jeans%' OR store_name LIKE '%Jeans%')
AND product_status = 1 
AND category_status = 1 
AND product_excluded = 0 
AND product_feed_status = 1 
AND store_status = 1 
AND shipping_location_currency_code = 'AUD' 
AND product_image_path IS NOT NULL 
AND product_channel_id IN (1, 2, 3, 4) 
GROUP BY product_url
ORDER BY searchScore

答案 1 :(得分:0)

您按searchScore排序,这不是表字段,而是一些动态汇总的值。因此,MySQL不能使用索引进行排序,而是使用FileSort。这当然很慢。

现在,关于优化提示:

  1. 如果您的product_urlproduct_namestore_name不超过255个字符,则使用VARCHAR(255)甚至CHAR(255)。并确保product_url是索引字段(不是全文索引,而是普通索引)。实际上,所有3个字段都必须编入索引。

  2. 您确定需要使用MATCH AGAINST构造吗?如果你在那里使用REGEXP它会更快,但我不知道确切的要求。

  3. 它再次与p.1相关 - 你有字段为(VAR)CHAR(255) - 然后添加WHERE + GROUP BY中所有字段的复合索引,我的意思是: product_name,store_name,product_status,category_status,product_excluded,product_feed_status,store_status,shipping_location_currency_mode,product_image_path,product_channel_id,product_url。另外,您可能会将product_url作为单独的索引。

  4. 希望它会有所帮助。在我提出的修改之后,您应该在不到一秒的时间内执行此查询。