首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >很慢的处理MySQL语句,如何使它表现得更好?

很慢的处理MySQL语句,如何使它表现得更好?
EN

Stack Overflow用户
提问于 2015-02-04 14:58:21
回答 2查看 63关注 0票数 0

我有下面的MySQL语句,当产品数量增加时,它的执行速度非常慢。目前的说明如下:

代码语言:javascript
运行
复制
SELECT DISTINCT products.*, colors.value FROM products
LEFT OUTER JOIN product_fields colors ON colors.product_id = products.id AND colors.name = 'color' 
GROUP BY products.id
ORDER BY
    CASE WHEN merchant IN ('Merchant 1') THEN -1 ELSE RAND(1617116433) END,
    CASE WHEN category IN ('Category 1', 'Category 2') THEN -1 ELSE RAND(1617116433) END 
LIMIT 0, 30

为了说明这一点:有一个product和一个product_fields表。对于每一个productproduct_fields表中都有零条或多条记录。product_fields表中的字段之一是字段:name,其值为color,这是结果中唯一需要的字段值。

创建ORDER BY语句是因为我希望首先显示某个商家的所有产品,然后随机显示来自其他商家的其余产品。其次,来自某个类别(类别1和类别2)的所有产品必须首先显示在结果中。在此之后,随机显示其他类别的产品。

对于随机,我已经使用一个固定的数字来随机化所有的东西。不一定每次都是不同的。我只想要其余的产品在商品1和类别1之后随机列出,类别2的产品显示。

目前,的声明工作正常,虽然在大数据集上运行非常慢,但我认为ORDER BY正在使它变慢,但是我不知道如何解决这个问题。希望有人能在这个问题上给我指明正确的方向。

现在我已经为上面的语句运行了>>,这就是结果:

代码语言:javascript
运行
复制
+----+-------------+--------------+------+---------------+-------------+---------+----------------------------------------------+-------+---------------------------------+
| id | select_type | table        | type | possible_keys | key         | key_len | ref                                          | rows  | Extra                           |
+----+-------------+--------------+------+---------------+-------------+---------+----------------------------------------------+-------+---------------------------------+
|  1 | SIMPLE      | products     | ALL  | NULL          | NULL        | NULL    | NULL                                         | 10402 | Using temporary; Using filesort |
|  1 | SIMPLE      | colors       | ref  | product_key   | product_key | 767     | dbname.products.id                           |     1 |                                 |
+----+-------------+--------------+------+---------------+-------------+---------+----------------------------------------------+-------+---------------------------------+
2 rows in set (0.02 sec)

编辑2>>来澄清一些事情:使用RAND只是因为我希望在显示了来自特定“商人”和“类别”的所有产品之后,每个产品都被随机显示出来。但是下一次当用户访问这个网站的时候,订单可能是一样的,尽管我很在意。我只想让所有的,其他的产品,不要按特定的商人或类别分类。这就是RAND的意义所在。

感谢@spencer7593的精彩回答,我认为这一切归结为使用Using filesort选项对整个结果集进行排序(请参阅上面的解释)。因此,现在我如何解决这个问题,保持一种方式随机的结果,如上文一段所解释的。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-02-04 15:34:27

表达式RAND(1617116433)将在每次计算时返回相同的常量值。对于每一行都将返回相同的确切值。也就是说,用大于-1的文字数值替换该表达式将产生一个等效的结果。

如果确实希望为每一行分配伪随机值,则需要从函数中移除种子值。您需要使用RAND()为每一行获取不同的值。

作为一个示范,比较以下方面的结果:

代码语言:javascript
运行
复制
SELECT RAND(1617116433), RAND(1617116433), RAND(1617116433) ;
SELECT RAND(1617116433), RAND(), RAND() ;

(请注意,第二条语句将返回相同的值序列,每次运行。RAND()是一个伪随机数生成器,而不是真正的随机数生成器。)

无论哪种方式,在您的查询中,函数都将对每一行进行计算,然后对整个结果集进行排序。(“解释”将显示“使用文件短”)。

最后应用LIMIT子句,对整个结果集进行排序,然后从排序集返回前30行。(这可以避免返回大量的行,但MySQL服务器仍在准备整个集合。)

这可能是你的查询“慢”的最大原因。

DISTINCT的用法有点奇怪,您已经有了一个GROUP BY子句,它确保来自产品的id是唯一的。规范模式是在colors.value子句中包括GROUP BY

另外,是否需要从products表返回每一列?我们更希望看到要返回在SELECT列表中枚举的列列表,而不是依赖*

product_fields表进行适当的索引可以提高联接操作的性能。

代码语言:javascript
运行
复制
... ON `product_fields` (`product_id`, `name`, `value`)

(我们预计解释输出应该显示该表的“使用索引”。)

但是,这并不能满足访问products表中每一行的需要,并为products.id的每个不同值计算RAND()函数(两次)。

( products表上的覆盖索引也可能带来很小的好处,但我认为这是可以忽略的。)

我会像这样写这个查询,但这不能解决“大石头”性能问题:

代码语言:javascript
运行
复制
SELECT p.id
     , p.???
     , p.???
     , c.value
  FROM (SELECT RAND(1617116433)) i 
 CROSS
  JOIN products p
  LEFT
  JOIN product_fields c
    ON c.product_id = p.id
   AND c.name = 'color'
 GROUP BY p.id, c.value
 ORDER
    BY CASE WHEN p.merchant IN ('Merchant 1') THEN -1 ELSE RAND() END
     , CASE WHEN p.category IN ('Category 1', 'Category 2') THEN -1 ELSE RAND() END 
 LIMIT 0, 30
票数 2
EN

Stack Overflow用户

发布于 2015-02-04 15:03:30

尝试在explain前面使用select关键字运行查询。它将告诉您使用了什么索引(如果有的话)。

索引是在MySQL中具有良好性能的关键。在本例中,您需要颜色索引(product_id,name)。

即使如此,这将始终运行一个完整的表扫描产品。您应该尝试在查询中添加限制的where-statement。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/28324431

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档