Mysql子查询工作缓慢

时间:2014-12-10 12:00:19

标签: mysql subquery

我使用view在mysql中有子查询和concat。通常,查询工作很快,但如果查询的子查询工作非常缓慢。

此代码运行迅速(大约1秒)

CREATE OR REPLACE VIEW ilceler AS ( 

SELECT I.id, I.modulid, I.id as icerikidsi,
MAX(IF(D.alanid=2,D.textkisa,NULL)) AS ilceadi,
MAX(IF(D.alanid=2,D.id,NULL)) AS ilceadi_i,
I.seo_description, 
I.seo_h1, 
I.seo_h2, 
I.seo_h3, 
I.seo_h4, 
I.seo_imgalt,
I.seo_imgtitle, 
I.seo_keywords, 
I.seo_pagetitle,
I.seo_url,
I.seo_urltitle 

FROM datalar as D LEFT JOIN icerikler as I ON D.icerikid=I.id WHERE D.modulid='3' GROUP BY D.icerikid ORDER BY sehiradi asc )

但是这段代码的工作非常缓慢(大约20秒)

CREATE OR REPLACE VIEW ilceler AS ( 

SELECT I.id, I.modulid, I.id as icerikidsi,
MAX(IF(D.alanid=2,D.textkisa,NULL)) AS ilceadi,
MAX(IF(D.alanid=2,D.id,NULL)) AS ilceadi_i,

( SELECT CONVERT ( GROUP_CONCAT(D2.id SEPARATOR ' ₋ ' ) USING UTF8 )FROM datalar as D1 
LEFT JOIN datalar as D2 ON D1.iliskialanid=D2.id WHERE D1.modulid='3' AND D1.alanid='3' AND D1.icerikid=icerikidsi ) as sehiradi_a ,
( SELECT GROUP_CONCAT(iliskiid SEPARATOR ' ₋ ') FROM datalar WHERE alanid='3' AND modulid='3' AND icerikid=icerikidsi ) as sehiradi_i,

( SELECT GROUP_CONCAT(D2.textkisa SEPARATOR ' ₋ ' ) FROM datalar as D1 LEFT JOIN datalar as D2 ON D1.iliskialanid=D2.id 
WHERE D1.modulid='3' AND D1.alanid='3' AND D1.icerikid=icerikidsi ) as sehiradi ,

I.seo_description, 
I.seo_h1, 
I.seo_h2, 
I.seo_h3, 
I.seo_h4, 
I.seo_imgalt,
I.seo_imgtitle, 
I.seo_keywords, 
I.seo_pagetitle,
I.seo_url,
I.seo_urltitle 

FROM datalar as D LEFT JOIN icerikler as I ON D.icerikid=I.id WHERE D.modulid='3' GROUP BY D.icerikid ORDER BY sehiradi asc )

为什么呢?我哪里弄错了? 我在等你的帮助。

1 个答案:

答案 0 :(得分:1)

您的子查询依赖于select的值,因此需要为每个返回的行执行这3个子查询中的每一个。对于少量行,这不是问题,但是有很多行可以快速累加。

正常的解决方案是连接子查询(因此对所有行都进行一次,你只需加入结果)。

例如: -

SELECT I.id, 
        I.modulid, 
        I.id as icerikidsi,
        MAX(IF(D.alanid=2,D.textkisa,NULL)) AS ilceadi,
        MAX(IF(D.alanid=2,D.id,NULL)) AS ilceadi_i,
        sub1.sehiradi_a ,
        sub2.sehiradi_i,
        sub1.sehiradi ,
        I.seo_description, 
        I.seo_h1, 
        I.seo_h2, 
        I.seo_h3, 
        I.seo_h4, 
        I.seo_imgalt,
        I.seo_imgtitle, 
        I.seo_keywords, 
        I.seo_pagetitle,
        I.seo_url,
        I.seo_urltitle 
FROM datalar as D 
LEFT JOIN icerikler as I ON D.icerikid=I.id 
LEFT OUTER JOIN 
(
    SELECT D1.icerikid, CONVERT ( GROUP_CONCAT(D2.id SEPARATOR ' ₋ ' ) USING UTF8 ) AS sehiradi_a, GROUP_CONCAT(D2.textkisa SEPARATOR ' ₋ ' ) AS sehiradi
    FROM datalar as D1 
    LEFT JOIN datalar as D2 ON D1.iliskialanid=D2.id 
    WHERE D1.modulid='3' 
    AND D1.alanid='3' 
    GROUP BY D1.icerikid
) sub1
ON sub1.icerikid = I.id 
LEFT OUTER JOIN 
( 
    SELECT icerikid, GROUP_CONCAT(iliskiid SEPARATOR ' ₋ ') AS sehiradi_i
    FROM datalar 
    WHERE alanid='3' 
    AND modulid='3' 
    GROUP BY icerikid
) sub2
ON sub2.icerikid = I.id 
WHERE D.modulid='3' 
GROUP BY D.icerikid 
ORDER BY sehiradi asc 

或者根据您的实际数据库设计,您可以将其简化为

SELECT I.id, 
        I.modulid, 
        I.id as icerikidsi,
        MAX(IF(D.alanid=2,D.textkisa,NULL)) AS ilceadi,
        MAX(IF(D.alanid=2,D.id,NULL)) AS ilceadi_i,
        sub1.sehiradi_a ,
        sub1.sehiradi_i,
        sub1.sehiradi ,
        I.seo_description, 
        I.seo_h1, 
        I.seo_h2, 
        I.seo_h3, 
        I.seo_h4, 
        I.seo_imgalt,
        I.seo_imgtitle, 
        I.seo_keywords, 
        I.seo_pagetitle,
        I.seo_url,
        I.seo_urltitle 
FROM datalar as D 
LEFT JOIN icerikler as I ON D.icerikid=I.id 
LEFT OUTER JOIN 
(
    SELECT D1.icerikid, 
            CONVERT ( GROUP_CONCAT(D2.id SEPARATOR ' ₋ ' ) USING UTF8 ) AS sehiradi_a, 
            GROUP_CONCAT(D2.textkisa SEPARATOR ' ₋ ' ) AS sehiradi,
            GROUP_CONCAT(DISTINCT D1.iliskiid SEPARATOR ' ₋ ') AS sehiradi_i
    FROM datalar as D1 
    LEFT JOIN datalar as D2 ON D1.iliskialanid=D2.id 
    WHERE D1.modulid='3' 
    AND D1.alanid='3' 
    GROUP BY D1.icerikid
) sub1
ON sub1.icerikid = I.id 
WHERE D.modulid='3' 
GROUP BY D.icerikid 
ORDER BY sehiradi asc 

但是这里有一个小问题。在MySQL中,视图不能包含从子查询中获取数据的FROM。因此,要在视图中使用此语法,您需要将子查询拆分为自己的视图。然后你可以加入视图而不是子查询。