2009-01-02 160 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查詢優化器」。