簡體   English   中英

php中MySQL查詢的優化

[英]Optimization of a MySQL query in php

如何優化以下查詢

CREATE TABLE $fullTableName AS (
SELECT COUNT(*) AS `impCnt`,
IF(COUNT(*)>7,7,COUNT(*)) AS `impGroup`,
MIN(ad.`created`) AS `dateFirstImp`,
ad.sid,
IF(cl.`clicks` IS NULL, 0, cl.`clicks`) AS `clickCnt`,
st.`panelistID` AS panelistID,
SUBSTRING_INDEX(GROUP_CONCAT(NULLIF(lbs.`site`, '') ORDER BY lbs.`table-order`,lbs.`value-order` ASC SEPARATOR '~'),'~',1) as 'site',
SUBSTRING_INDEX(GROUP_CONCAT(NULLIF(lbs.`dimension`, '') ORDER BY lbs.`table-order`,lbs.`value-order` ASC SEPARATOR '~'),'~',1) as 'dimension'
FROM table1 ad
LEFT JOIN (
    SELECT t.`parameter` as 'parameter', v.`value` as 'value',
    IF(FIND_IN_SET('site',t.attributes),v.`site`,null) as 'site',
    IF(FIND_IN_SET('placement',t.attributes),v.`placement`,null) as 'placement',
    IF(FIND_IN_SET('format',t.attributes),v.`format`,null) as 'format',
    IF(FIND_IN_SET('creative',t.attributes),v.`creative`,null) as 'creative',
    IF(FIND_IN_SET('mediaOwner',t.attributes),v.`mediaOwner`,null) as 'mediaOwner',
    IF(FIND_IN_SET('targeting',t.attributes),v.`targeting`,null) as 'targeting',
    IF(FIND_IN_SET('dimension',t.attributes),v.`dimension`,null) as 'dimension',
    t.`order` as 'table-order', v.`order` as 'value-order' FROM table2 t
    JOIN table3 v ON (t.tableID=v.tableID) WHERE t.campaignID = 1856
    AND t.`active`=1 AND t.`ignore`=0 ORDER BY t.`order`,v.`order`
) lbs ON ($string)
LEFT JOIN (
    SELECT cl2.`memberid` as memberid,
    cl2.`panelid` as panelid,COUNT(*) as clicks
    FROM table4 cl2 WHERE 1 AND (1) GROUP BY cl2.`memberid`,cl2.`panelid`
) cl
ON (ad.`memberid`=cl.`memberid` AND ad.`panelid`=cl.`panelid`)
LEFT JOIN table5 st
ON (ad.`memberid`=st.`panelistID` AND ad.`panelid`=st.`panelID`)
JOIN table6 ef
ON (ef.`panelID`=st.`panelID` AND ef.`panelistID`=st.`panelistID`)
WHERE 1 AND (1) GROUP BY ad.`memberid`, ad.`panelid` ORDER BY ad.`memberid` ASC, ad.`panelid` ASC)

想到了各種各樣的問題......首先,出於可讀性目的對查詢進行一些清理......

SELECT 
      COUNT(*) AS impCnt,
      IF( COUNT(*) > 7, 7 , COUNT(*) ) AS impGroup,
      MIN(ad.created) AS dateFirstImp,
      ad.sid,
      IF(cl.clicks IS NULL, 0, cl.clicks ) AS clickCnt,
      st.panelistID,
      SUBSTRING_INDEX(GROUP_CONCAT(NULLIF(lbs.site, '') ORDER BY lbs.`table-order`, lbs.`value-order` ASC SEPARATOR '~'),'~',1) as 'site',
      SUBSTRING_INDEX(GROUP_CONCAT(NULLIF(lbs.dimension, '') ORDER BY lbs.`table-order`,lbs.`value-order` ASC SEPARATOR '~'),'~',1) as 'dimension'
   FROM 
      table1 ad
         LEFT JOIN ( SELECT 
                           t.`parameter` as 'parameter', 
                           v.`value` as 'value',
                           IF(FIND_IN_SET('site',t.attributes),v.site,null) as 'site',
                           IF(FIND_IN_SET('placement',t.attributes),v.placement,null) as 'placement',
                           IF(FIND_IN_SET('format',t.attributes),v.format,null) as 'format',
                           IF(FIND_IN_SET('creative',t.attributes),v.creative,null) as 'creative',
                           IF(FIND_IN_SET('mediaOwner',t.attributes),v.mediaOwner,null) as 'mediaOwner',
                           IF(FIND_IN_SET('targeting',t.attributes),v.targeting,null) as 'targeting',
                           IF(FIND_IN_SET('dimension',t.attributes),v.dimension,null) as 'dimension',
                           t.`order` as 'table-order', 
                           v.`order` as 'value-order' 
                        FROM 
                           table2 t
                              JOIN table3 v 
                                 ON t.tableID = v.tableID
                        WHERE 
                               t.campaignID = 1856
                           AND t.active = 1 
                           AND t.ignore = 0 
                        ORDER BY 
                           t.`order`,
                           v.`order` ) lbs 
            ON ($string)

         LEFT JOIN ( SELECT 
                           cl2.memberid as memberid,
                           cl2.panelid as panelid,
                           COUNT(*) as clicks
                        FROM 
                           table4 cl2 
                        WHERE 
                           1 AND (1) 
                        GROUP BY 
                           cl2.memberid,
                           cl2.panelid ) cl
            ON ad.memberid = cl.memberid
            AND ad.panelid = cl.panelid

         LEFT JOIN table5 st
            ON ad.memberid = st.panelistID
            AND ad.panelid = st.panelID

         JOIN table6 ef
            ON ef.panelID = st.panelID
            AND ef.panelistID = st.panelistID 

   WHERE 
      1 AND (1) 
   GROUP BY 
      ad.memberid, 
      ad.panelid
   ORDER BY 
      ad.memberid ASC, 
      ad.panelid ASC

您顯然試圖通過您的表名進行泛型化,但使用別名可以很好地顯示關系。

  1. 您加入基於 ($string) 的子查詢別名“lbs”,但沒有提供任何可能是什么的上下文/樣本——過濾和/或實際加入標准?

  2. 作為“lbs”別名基礎的內部選擇僅在最終外部查詢中使用“站點”和“維度”列......為什么對所有其他列執行 FIND_IN_SET 。

  3. 基於“lbs”查詢,您的 table2(t 別名)應該在(campaignID, active, ignore, order )上有一個復合索引,以幫助優化查詢的那部分和 order by 子句。

  4. 針對您的(廣告別名)表的最終 group by / order by 應至少在 ( memberid, panelid ) 上有一個復合索引,並根據您從“廣告”中尋找的“標准”在這些列的前面添加額外的列桌子。

  5. 根據您的“WHERE 1 AND (1)”標准,您的(cl2 別名)應該在( memberid, panelid )加上附加列上有一個復合索引,這些列是不明確的,只是實際過濾標准的占位符。 如果沒有示例真實上下文,我們就無法為您提供更好的索引列優化。

  6. “1 AND (1)”的最后一個 WHERE 子句......與#5 相同的歧義。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM