2012-01-29 128 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