2009-01-02 162 views
1

我有一个有点复杂的查询大约100K行。MySQL与SQL Server Express性能比较

查询在SQL Server Express中13秒运行(在我的dev的盒子上运行)

具有相同的索引和表同样的查询将接管15分钟以上对MySQL 5.1中运行(在我的箱子生产运行 - 功能更加强大,并且测试了100%的资源)有时,查询会导致计算机崩溃,导致内存不足错误。

我在做什么MySQL错误?为什么需要这么长时间?如果有效的指标是可用

select e8.* 
from table_a e8 
inner join (
    select max(e6.id) as id, e6.category, e6.entity, e6.service_date 
    from (
     select e4.* 
     from table_a e4 
     inner join (
      select max(e2.id) as id, e3.rank, e2.entity, e2.provider_id, e2.service_date 
      from table_a e2 
      inner join (
       select min(e1.rank) as rank, e1.entity, e1.provider_id, e1.service_date 
       from table_a e1 
       where e1.site_id is not null 
       group by e1.entity, e1.provider_id, e1.service_date 
      ) as e3 
      on e2.rank= e3.rank 
      and e2.entity = e3.entity 
      and e2.provider_id = e3.provider_id 
      and e2.service_date = e3.service_date 
      and e2.rank= e3.rank 
      group by e2.entity, e2.provider_id, e2.service_date, e3.rank 
     ) e5 
     on e4.id = e5.id 
     and e4.rank= e5.rank        
    ) e6 
    group by e6.category, e6.entity, e6.service_date 
) e7 
on e8.id = e7.id and e7.category = e8.category 
+1

我会更担心它崩溃了! – 2009-01-02 01:22:23

+0

大声笑 - 这就是为什么我要迁移到SQL Server ... – mson 2009-01-02 01:25:42

+0

说实话,我没有看到这里有一个真正的问题。 – 2009-01-02 01:26:22

回答

2

这个答案我最初试图发布到您的已删除问题,但并未表明这是MySQL的问题。我仍然会继续使用SQL Server来使用CTE重构查询,然后转换回嵌套查询(如果有的话)。对格式化抱歉,Jeff Atwood发给我原始的发布文本,我不得不重新格式化它。

很难做到没有数据,预期结果和好名字,但我会将所有嵌套查询转换成CTE,将它们堆叠起来,对它们进行有意义的命名和重构 - 从排除不使用的列开始。删除列不会导致改进,因为优化器非常聪明 - 但它会让您有能力改进您的查询 - 可能会分解出部分或全部CTE。我不确定你的代码在做什么,但是你可能会发现新的RANK()类型的函数很有用,因为它看起来像是在所有这些自连接中使用了一个回溯型的模式。

所以从这里开始吧。我已经研究过e7的改进,e7中没有使用的列可能表明对分组的可能性有缺陷或者不完整的想法,但是如果这些列确实是不必要的,那么这可能会在e6中一路回到你的逻辑, e5和e3。如果e7中的分组是正确的,那么您可以消除结果和连接中的所有内容,但最大值(id)。我看不出为什么每个类别会有多个MAX(id),因为当你加入时这会增加你的结果,所以MAX(id)在类别中必须是唯一的,在这种情况下,类别在连接中是多余的。

WITH e3 AS (
select min(e1.rank) as rank, 
e1.entity, 
e1.provider_id, 
e1.service_date 
from table_a e1 
where e1.site_id is not null 
group by e1.entity, e1.provider_id, e1.service_date 
) 

,e5 AS (
select max(e2.id) as id, 
e3.rank, 
e2.entity, 
e2.provider_id, 
e2.service_date 
from table_a e2 
inner join e3 
on e2.rank= e3.rank 
and e2.entity = e3.entity 
and e2.provider_id = e3.provider_id 
and e2.service_date = e3.service_date 
and e2.rank= e3.rank 
group by e2.entity, e2.provider_id, e2.service_date, e3.rank 
) 

,e6 AS (
select e4.* -- switch from * to only the columns you are actually using 
from table_a e4 
inner join e5 
on e4.id = e5.id 
and e4.rank= e5.rank 
) 

,e7 AS (
select max(e6.id) as id, e6.category -- unused, e6.entity, e6.service_date 
from e6 
group by e6.category, e6.entity, e6.service_date 
-- This instead 
-- select max(e6.id) as id 
-- from e6 
-- group by e6.category, e6.entity, e6.service_date 
) 

select e8.* 
from table_a e8 
inner join e7 
on e8.id = e7.id 
and e7.category = e8.category 
-- THIS INSTEAD on e8.id = e7.id 
0

100,000行不应该采取13秒。我怀疑这种差异是由于SQL服务器具有比MySQL更健壮的查询优化器。 MySQL所具有的更多是按照SQL解析器的顺序而不是优化器。

您需要提供更多信息 - 所有参与表的完整模式以及每个参数的完整索引列表,供初学者参考。

然后对数据是关于什么以及查询打算产生什么的一些想法。一些用例的顺序。

1

这将是有趣的解释计划与两个看看有什么区别。我不确定这是一个苹果和橙色的比较,但我会很好奇。

我不知道this是否可以提供帮助,但是这是第一次搜索“mysql查询优化器”。