【问题标题】:MySQL very slow with OrderByMySQL 使用 OrderBy 非常慢
【发布时间】:2012-06-03 14:36:27
【问题描述】:

在应用 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的解释

+----+-------------+--------+------ --+----------------------------------------------- -------------------------------------------------- --------------------------+------------------------ -+---------+-------------------------- ------------+--------+---------------- ------------------+
|编号 |选择类型 |表|类型 |可能的键 |关键 | key_len |参考 |行 |额外 |
+----+--------------+--------+--------+ -------------------------------------------------- -------------------------------------------------- ------------------------------------+-------------+- --------+----------------------------------------- ---------+--------+------------------------------- ---------------+
| 1 |初级 |  |全部 | \N | \N | \N | \N | 5866 |使用文件排序 |
| 2 |派生 |产品 |参考 | 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 |使用哪里;使用临时的;使用文件排序 |
| 2 |派生 |商店 | eq_ref | PRIMARY,idx_storestatus |初级 | 4 | products.product_store_id | 1 |使用位置 |
| 2 |派生 |产品类别 |参考 | PRIMARY,idx_category,idx_categoryproduct | idx_categoryproduct | 4 | products.product_id | 1 | |
| 2 |派生 |类别 | eq_ref |初级,新索引1 |初级 | 4 | product_categories.product_category_category_id | 1 |使用位置 |
| 2 |派生 |产品颜色 |参考 | idx_colourproduct | idx_colourproduct | 5 | products.product_id | 2 | |
| 2 |派生 |颜色 | eq_ref |初级 |初级 | 4 | product_colours.product_colour_colour_id | 1 | |
| 2 |派生 |店铺配送 |参考 | idx_storeshippingstore,idx_storeshippinglocation | idx_storeshippingstore | 5 |商店.store_id | 4 |使用位置 |
| 2 |派生 |运输地点 | eq_ref | PRIMARY,idx_shippinglocation |初级 | 4 | storeShipping.storeShipping_shipping_location_id | 1 |使用位置 |
| 2 |派生 |部分 | eq_ref |初级 |初级 | 4 | products.product_channel_id | 1 | |
+----+--------------+--------+--------+ -------------------------------------------------- -------------------------------------------------- ------------------------------------+-------------+- --------+----------------------------------------- ---------+--------+------------------------------- ---------------+

没有orderby

+--------+-------------+--------------------+-- ------+-------------------------------------------------------- -------------------------------------------------- ------------------------------+------------------ -----+---------+---------------------------------- ----------------+--------+------------------------ ----------------------+
|编号 |选择类型 |表|类型 |可能的键 |关键 | key_len |参考 |行 |额外 |
+--------+-------------+--------+-- ---+---------------------------------------------------------- -------------------------------------------------- ---------------------------------------+------------------------ --+---------+-------------------------- -------------+--------+--------------- ------------------+
| 1 |简单 |产品 |参考 | 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 |使用哪里;使用临时的;使用文件排序 |
| 1 |简单 |商店 | eq_ref | PRIMARY,idx_storestatus |初级 | 4 | products.product_store_id | 1 |使用位置 |
| 1 |简单 |产品类别 |参考 | PRIMARY,idx_category,idx_categoryproduct | idx_categoryproduct | 4 | products.product_id | 1 | |
| 1 |简单 |类别 | eq_ref |初级,新索引1 |初级 | 4 | product_categories.product_category_category_id | 1 |使用位置 |
| 1 |简单 |产品颜色 |参考 | idx_colourproduct | idx_colourproduct | 5 | products.product_id | 2 | |
| 1 |简单 |颜色 | eq_ref |初级 |初级 | 4 | product_colours.product_colour_colour_id | 1 | |
| 1 |简单 |店铺配送 |参考 | idx_storeshippingstore,idx_storeshippinglocation | idx_storeshippingstore | 5 |商店.store_id | 4 |使用位置 |
| 1 |简单 |运输地点 | eq_ref | PRIMARY,idx_shippinglocation |初级 | 4 | storeShipping.storeShipping_shipping_location_id | 1 |使用位置 |
| 1 |简单 |部分 | eq_ref |初级 |初级 | 4 | products.product_channel_id | 1 | |
+--------+-------------+--------+-- ---+---------------------------------------------------------- -------------------------------------------------- ---------------------------------------+------------------------ --+---------+-------------------------- -------------+--------+--------------- -------------------+

你们能做的任何事都可以让我振作起来!

谢谢!

【问题讨论】:

  • 为什么你在父查询中使用ORDER BY 而不仅仅是对子查询应用ORDER BY 子句?您的查询不必要地对结果进行了两次排序(一次用于分组操作,另一次用于排序操作)。
  • 我想我不明白你来自哪里,我已经按照这个建议的 orderby 格式化了我的方式。这在几个过度查询中有所帮助,它也在一定程度上帮助了这一点。 stackoverflow.com/questions/884661/…
  • 我尝试运行您发布的查询的编辑版本,但仍然需要 10 秒才能返回。
  • 谁发布的编辑版本?我没有对您的查询发布任何编辑(我只整理了EXPLAIN 输出表)。也许您打算对以下答案之一发表评论?
  • 哦,是的,对不起那家伙。我误读了。

标签: mysql sql-order-by


【解决方案1】:

您按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 作为单独的索引。

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

【讨论】:

  • 我已经将所有需要它的字段设置为 varchar(255),我还尽可能地设置了索引。我刚刚添加了一个索引,其中包含您建议的产品表中的字段。我是否认为我不能将单独表中的字段索引到一个索引中?我现在正在考虑使用 REGEXP,但到目前为止速度没有提高。
  • 抱歉,忘记了这些字段来自不同的表。当然,您不能将它们抓取到一个索引中,但需要至少按表对它们进行分组......我想玩这个查询。您是否有机会在某处上传转储(带有假值)?
【解决方案2】:

我稍微修改了您的查询。你能试试吗? 也请INDEX 专栏product_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

【讨论】:

  • 运行此返回 0 个结果。另外据我所知,没有orderby?
  • 没有 MATCH AGAINST,它被 = 取代,因此它不起作用。放在那里LIKE而不是=并用%包围文本。然后它应该工作
  • 它确实有效,但返回时间为 17 秒,所以它比我原来的查询要慢。
猜你喜欢
  • 1970-01-01
  • 2014-07-16
  • 1970-01-01
  • 2021-05-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-24
  • 2019-08-02
相关资源
最近更新 更多