Mysql 是否有任何方法可以使用连接正确地替换条件子查询并优化这些类型查询?

Mysql 是否有任何方法可以使用连接正确地替换条件子查询并优化这些类型查询?,mysql,join,optimization,subquery,Mysql,Join,Optimization,Subquery,我正在寻找通过删除子查询和重新组织可能的索引来优化这些查询的好方法,但我还是坚持了下来 第一 选择 `客户端`.`name`、`clients`.`id` 从…起 `客户` 哪里 `我不在 从“订单”中选择“订单”。“客户id” 其中'orders'。'order_date'从现在开始-间隔7天到现在 ; 图例:过去7天未下订单的客户名称 或者根本没有下订单 看起来不错,效果不错,但这让我怀疑 第二 选择 `客户端`.`name`、`clients`.`id`、COUNT* 从…起 `客户` 上

我正在寻找通过删除子查询和重新组织可能的索引来优化这些查询的好方法,但我还是坚持了下来

第一

选择 `客户端`.`name`、`clients`.`id` 从…起 `客户` 哪里 `我不在 从“订单”中选择“订单”。“客户id” 其中'orders'。'order_date'从现在开始-间隔7天到现在 ; 图例:过去7天未下订单的客户名称 或者根本没有下订单

看起来不错,效果不错,但这让我怀疑

第二

选择 `客户端`.`name`、`clients`.`id`、COUNT* 从…起 `客户` 上的内部联接'orders' `客户`.`id`=`orders`.`customer\u id` 按订单分组。`customer_id`按计数的订单*DESC,`id`限制0,5; 图例:店内订单最多的前五名客户

还有更好的主意吗

第三

选择 `客户`.`名称` ,合计“商品”。“价格”为“总价”` ,伯爵* 从…起 `命令` 上的内部联接“客户端” `订单`.`customer\u id`=`clients`.`id` 内部连接“商品” `订单`.`item\u id`=`商品`.`id` 分组 `订单`.`customer\u id` 订购人 `总价 限度 0,10 ; 图例:订单金额最高的前10名客户

解决方案太慢,不知道索引

第四

选择 `商品名称` 从…起 `商品` “身份证”不在哪里 选择 `订单`.`项目标识` 从…起 `命令` 哪里 `订单`.`状态`=“完成” ; 图例:未交付订单的所有产品的名称

再次-子查询


感谢您的帮助和任何想法

我相信not in as函数调用以及加入另一个表并让MySql进行比较可能会有点昂贵。为此,我将让程序执行连接值的查询,并排除程序中的。对于第二次和第三次,我相信你做得最好。对于第一个和第四个查询,做子查询的成本确实更高,正如我前面提到的,对于这些查询,我可能只做一个查询,将我需要的数据连接起来,并在我正在编写的程序中使用它们。

FWIW,称我为老式查询,但我会以这种方式编写第一个查询,在customer\u id、order\u date上使用一个复合索引

SELECT c.name
     , c.id
  FROM clients c
  LEFT
  JOIN orders o 
    ON o.customer_id = c.id
   AND o.order_date BETWEEN NOW() - INTERVAL 7 DAY AND NOW()
 WHERE o.id IS NULL;
第二个查询很好,但我会这样写,同样使用上面提到的索引

SELECT c.name
     , c.id
     , COUNT(*) total
  FROM clients c
  JOIN orders o
    ON o.customer_id = c.id 
 GROUP  
    BY c.name
     , c.id
 ORDER 
    BY total DESC
     , id 
 LIMIT 0,5;
再一次,第三个看起来不错。我觉得这更容易阅读:

SELECT c.name
     , SUM(m.price) TotalPrice
     , count(*) quantity
  FROM clients c
  JOIN orders o
    ON o.customer_id = c.id
  JOIN merchandise m
    ON m.id = o.item_id 
 GROUP 
    BY c.name
     , c.id
 ORDER 
    BY TotalPrice DESC
 LIMIT 0,10;
与第一个问题相同,但有一个关于item_id,status的综合索引,我会这样写第四个问题-虽然不存在,但可能会更快:

SELECT m.name
  FROM merchandise m
  LEFT
  JOIN orders o
    ON o.item_id = m.id
   AND o.status = 'complete'
 WHERE o.item_id IS NULL;

如果你一次只问一个问题会更好time@scaisEdge,我决定最好不要在同一类型中使用类似问题类型的垃圾邮件。我想这对社区成员来说会更好更方便谢谢。还有一些老式方法的基准测试:1-st:w/o索引连接平均575845秒,子查询平均0246秒。平均连接速度慢234倍w索引连接速度慢0030秒,子查询速度快0203平均连接速度快6,76倍更大的数据集的显著差异相对较小,例如,连接速度甚至慢500倍,索引带来的加速效益仅为第4位的20%,数据集更大,没有索引连接,平均时间为245714秒,子查询时间为0438秒。平均连接速度约为561倍,索引连接速度约为0015秒,子查询平均连接速度约为03745倍。平均连接速度约为24,97倍。使用旧方法解决方案时,如果没有相应的索引,则极不推荐使用!这将导致急剧减速和极其巨大的负载。但是,有了索引,他们将能够获得良好的性能提升,特别是在旧10G RAM笔记本上生成的大型数据集基准上,Ubuntu作为操作系统,默认配置mysql服务器5.7.26对不起,注释正文中的格式不好,我不知道为什么,但对newlinesbut的堆栈剪切,奇怪的是,第二次查询大约慢了2倍——1191秒对0585秒,第三次查询大约慢了15%——3854秒对3306秒是的,子查询和in/not in相对来说已经足够昂贵了。至少如果你有相应的索引。在另一种情况下,它们并不像你第一眼看到的那样糟糕和沉重。但是,同样令我惊讶的是,对于测试数据集来说,第三个请求非常慢,大约3秒以上。遗憾的是,我现在既找不到好的索引,也找不到其他解决方案