2012-01-29 126 views
1

這個問題已被多次詢問,我確定,但每種情況都不一樣。聯盟所有查詢花費的時間太長

我有一臺強大的2GB內存的計算機上安裝MySQL,它不會做太多,所以計算機就足夠了。

下面的查詢已建成爲一個觀點:

create view view_orders as 

select distinct 

    tbl_orders_order.order_date AS sort_col, 
    tbl_orders_order.order_id AS order_id, 
_utf8'website' AS src,tbl_order_users.company AS company, 
tbl_order_users.phone AS phone, 
tbl_order_users.full_name AS full_name, 
time_format(tbl_orders_order.order_date,_utf8'%H:%i') AS c_time, 
date_format(tbl_orders_order.order_date,_utf8'%d/%m/%Y') AS c_date, 
tbl_orders_order.comments AS comments, 
tbl_orders_order.tmp_cname AS tmp_cname, 
tbl_orders_order.tmp_pname AS tmp_pname, 
count(tbl_order_docfiles.docfile_id) AS number_of_files, 
(case tbl_orders_order.status when 1 then _utf8'completed' when 2 then _utf8'hc' when 0 then _utf8'not-completed' when 3 then _utf8'hc-canceled' end) AS status, 

tbl_orders_order.employee_name AS employee_name, 
tbl_orders_order.status_date AS status_date, 
tbl_orders_order.cancel_reason AS cancel_reason 

from 
     tbl_orders_order left join tbl_order_users on tbl_orders_order.user_id = tbl_order_users.user_id 
    left join 
     tbl_order_docfiles on tbl_order_docfiles.order_id = tbl_orders_order.order_id 

    group by 
     tbl_orders_order.order_id 



union all 

select distinct tbl_h.h_date AS sort_col, 
(case tbl_h.sub_oid when 0 then tbl_h.order_number else concat(tbl_h.order_number,_utf8'-',tbl_h.sub_oid) end) AS order_id, 
(case tbl_h.type when 1 then _utf8'פקס' when 2 then _utf8'email' end) AS src,_utf8'' AS company, 
_utf8'' AS phone,_utf8'' AS full_name,time_format(tbl_h.h_date,_utf8'%H:%i') AS c_time, 
date_format(tbl_h.h_date,_utf8'%d/%m/%Y') AS c_date,_utf8'' AS comments,tbl_h.client_name AS tmp_cname, 
tbl_h.project_name AS tmp_pname, 
tbl_h.quantity AS number_of_files, 
_utf8'completed' AS status, 
tbl_h.computer_name AS employee_name, 
_utf8'' AS status_date, 
_utf8'' AS cancel_reason 

from tbl_h; 

查詢中使用UNION,比我瞭解UNION ALL的文章,現在使用的是。

查詢本身需要大約3秒鐘的時間(UNION需要4.5-5.5秒) 單獨的每個部分以秒爲單位運行。

應用程序會對此視圖進行排序和選擇,這會使處理時間更長 - 查詢緩存大約6秒,如果數據更改大約12秒或更長。

我沒有看到其他方式來結合這兩個結果,因爲這兩個排序需要顯示給用戶,我猜我做的事情是錯誤的。

當然這兩個表都使用主鍵。

UPDATE !!!!

它並沒有幫助,我從聯合查詢中得到了utf8/case/date_format,並刪除了區別,現在查詢需要4秒(甚至更長)。 查詢無case/date/utf8(僅聯合)縮短爲2.3秒(0.3秒改進)。

創建視圖view_orders作爲

select *, 
    (CASE src 
     WHEN 1 THEN 
      _utf8'fax' 
     WHEN 2 THEN 
      _utf8'mail' 
     WHEN 3 THEN 
      _utf8'website' 
    END) AS src, 

    time_format(order_date,'%H:%i') AS c_time, 
    date_format(order_date,'%d/%m/%Y') AS c_date, 

    (CASE status 
     WHEN 1 THEN 
      _utf8'completed' 
     WHEN 2 THEN 
      _utf8'hc handling' 
     WHEN 0 THEN 
      _utf8'not completed' 
     WHEN 3 THEN 
      _utf8'canceled' 
    END) AS status 

FROM 
(
select 

    o.order_date AS sort_col, 
    o.order_id, 
    3 AS src, 

    u.company, 
    u.phone, 
    u.full_name, 

    o.order_date, 

    o.comments, 
    o.tmp_cname, 
    o.tmp_pname, 
    count(doc.docfile_id) AS number_of_files, 

    o.status, 

    o.employee_name, 
    o.status_date, 
    o.cancel_reason 

from 
     tbl_orders_order o 
    LEFT JOIN 
     tbl_order_users u ON u.user_id = o.user_id 
    LEFT JOIN 
     tbl_order_docfiles doc ON doc.order_id = o.order_id 

    GROUP BY 
     o.order_id 

union all 

select 

    h.h_date AS sort_col, 
    (case h.sub_oid when 0 then h.order_number else concat(h.order_number,'-',h.sub_oid) end) AS order_id, 
    h.type as src, 

    '' AS company, 
    '' AS phone, 
    '' AS full_name, 

    h.h_date, 

    '' AS comments, 
    h.client_name AS tmp_cname, 
    h.project_name AS tmp_pname, 
    h.quantity AS number_of_files, 
    1 AS status, 

    h.computer_name AS employee_name, 
    '' AS status_date, 
    '' AS cancel_reason 

from tbl_h h 

+2

做兩個查詢需要是不同的?鑑於字段被返回,我猜測每個記錄都是唯一的。如果可能,刪除它。 – Digbyswift 2012-01-29 12:17:40

+0

可以肯定的是:'tbl_order_users.user_id'和'tbl_orders_order.order_id' _是主鍵,對嗎? – Thomas 2012-01-29 12:20:51

+0

是的,他們是.. – Avi 2012-01-29 22:40:39

回答

0

它可能與所述UNION觸發字符集轉換。例如,一個查詢中的cancel_reason被定義爲utf8,但另一個查詢中沒有指定。

檢查運行此查詢時是否有非常高的CPU峯值,這將表示轉換。

就我個人而言,我會首先完成原始數據的聯合,然後應用案例和轉換語句。但我不確定這會對錶現產生什麼影響。

+0

請在上面查看更新。 – Avi 2012-01-29 23:15:07

4

想想你使用的UNIONDISTINCT關鍵字。你的查詢是否真的會導致重複行?如果是,刪除重複的優化查詢可能會是這種形式的:

SELECT ... -- No "DISTINCT" here 
UNION 
SELECT ... -- No "DISTINCT" here 

大概沒有必要在兩個子查詢DISTINCT。如果重複是不可能的,請嘗試使用此表單。這將是你查詢的最快執行(不進一步優化子查詢):

SELECT ... -- No "DISTINCT" here 
UNION ALL 
SELECT ... -- No "DISTINCT" here 

理由:無論UNIONDISTINCT你的中間結果集的應用"UNIQUE SORT"操作。根據您的子查詢返回多少數據,這可能非常昂貴。這是原因之一,爲什麼忽略DISTINCT和更換UNION通過UNION ALL要快得多。

UPDATE另一個想法,如果你必須刪除重複:在內部查詢第一刪除重複和格式化日期和代碼只在外部查詢之後。這將加速"UNIQUE SORT"操作,因爲比較32/64-bit integers不是比較varchars更便宜:

SELECT a, b, date_format(c), case d when 1 then 'completed' else '...' end 
FROM (
    SELECT a, b, c, d ... -- No date format here 
    UNION 
    SELECT a, b, c, d ... -- No date format here 
) 
+0

OP的'UNION'的左半部分至少不需要'DISTINCT',因爲它使用主鍵列進行分組。 – 2012-01-29 13:26:44

+0

@AndriyM:好點。 – 2012-01-29 13:30:22

+0

請在上面查看更新。 – Avi 2012-01-29 23:14:56

0

你可以試試這個:

SELECT 
    o.order_date AS sort_col, 
    o.order_id AS order_id, 
    _utf8'website' AS src, 
    u.company AS company, 
    u.phone AS phone, 
    u.full_name AS full_name, 
    time_format(o.order_date,_utf8'%H:%i') AS c_time, 
    date_format(o.order_date,_utf8'%d/%m/%Y') AS c_date, 
    o.comments AS comments, 
    o.tmp_cname AS tmp_cname, 
    o.tmp_pname AS tmp_pname, 
    COALESCE(d.number_of_files, 0) AS number_of_files, 
    (CASE o.status WHEN 1 THEN _utf8'completed' 
        WHEN 2 THEN _utf8'hc' 
        WHEN 0 THEN _utf8'not-completed' 
        WHEN 3 THEN _utf8'hc-canceled' 
     END) AS status, 
    o.employee_name AS employee_name, 
    o.status_date AS status_date, 
    o.cancel_reason AS cancel_reason  
FROM 
     tbl_orders_order AS o 
    LEFT JOIN 
     tbl_order_users AS u 
    ON o.user_id = u.user_id 
    LEFT JOIN 
     (SELECT order_id 
       , COUNT(*) AS number_of_files 
     FROM tbl_order_docfiles 
     GROUP BY order_id 
     ) AS d 
    ON d.order_id = o.order_id 

UNION ALL 

SELECT 
    tbl_h.h_date AS sort_col, 
    ... 

FROM tbl_h 
+0

它卡住了我的mysql,沒有好的 – Avi 2012-02-01 01:23:41

+0

你是這樣運行的嗎?或者把它放在視圖中,然後添加'ORDER BY'? – 2012-02-01 10:25:02

+0

如果您在問題中添加了表,表的定義,索引和查詢計劃(EXPLAIN輸出),那將會很好。 – 2012-02-01 10:25:56