我的SQL查询缓慢(所有数据均正常工作)。我的问题是查询的工作量超过〜2sek。
SELECT CONCAT(YEAR(FROM_UNIXTIME(pixel.adddate)), '/', MONTHNAME(FROM_UNIXTIME(pixel.adddate))) AS period,
COUNT(pixel.id) AS clicks,
COUNT(postbacktracker.id) AS conversions,
CONCAT(HOUR(FROM_UNIXTIME(TRUNCATE(pixel.adddate / 3600, 0) * 3600)), ' - ', (HOUR(FROM_UNIXTIME(TRUNCATE(pixel.adddate / 3600, 0) * 3600)) + 1)) AS hour,
DAYNAME(FROM_UNIXTIME(TRUNCATE(pixel.adddate / 86400, 0) * 86400)) AS DAY,
CONCAT(YEAR(FROM_UNIXTIME(pixel.adddate)), '/', WEEK(FROM_UNIXTIME(pixel.adddate))) AS week,
MONTHNAME(FROM_UNIXTIME(pixel.adddate)) AS MONTH,
YEAR(FROM_UNIXTIME(pixel.adddate)) AS YEAR,
FROM_UNIXTIME(MIN(pixel.adddate)) AS min_date,
FROM_UNIXTIME(MAX(pixel.adddate+1)) AS max_date,
pixel.adddate AS adddate,
products.id AS OfferID,
products.name AS name,
campaign.id AS id,
campaign.name AS campaign_name,
pixel.transaction_id AS TransactionID,
pixel.url AS url,
campaign.mkey AS mkey,
team_users.first_name AS first_name,
team_users.last_name AS lastname,
team_users.company AS company,
team_users.email AS email,
team_users.hasoffersid AS affiliateid,
COUNT(userdata.id) AS user_exists,
SUM(userdata.orders) AS total_operations,
COUNT(CASE
WHEN userdata.orders != 0 THEN 1
END) AS total_sales,
COUNT(CASE
WHEN userdata.orders = 1 THEN 1
END) AS sales_without_upsells,
COUNT(CASE
WHEN userdata.orders > 1 THEN 1
END) AS sales_with_upsells,
SUM(userdata.pvalue_sum) AS total_sales_sum,
SUM(CASE
WHEN userdata.orders = 1 THEN userdata.pvalue_sum
END) AS sales_wo_up,
SUM(CASE
WHEN userdata.orders > 1 THEN userdata.pvalue_sum
END) AS sales_w_up,
(SUM(CASE
WHEN userdata.orders = 1 THEN userdata.pvalue_sum
END)/COUNT(CASE
WHEN userdata.orders = 1 THEN 1
END)) AS AOVCheckout,
(SUM(CASE
WHEN userdata.orders > 1 THEN userdata.pvalue_sum
END)/COUNT(CASE
WHEN userdata.orders > 1 THEN 1
END)) AS AOVinclupsells,
(((SUM(CASE
WHEN userdata.orders = 1 THEN userdata.pvalue_sum
END)/COUNT(CASE
WHEN userdata.orders = 1 THEN 1
END)) + (SUM(CASE
WHEN userdata.orders > 1 THEN userdata.pvalue_sum
END)/COUNT(CASE
WHEN userdata.orders > 1 THEN 1
END)))/2) AS AOVall,
COUNT(CASE
WHEN userdata.orders = 0 THEN 1
END) AS presale,
COUNT(CASE
WHEN userdata.orders != 0 THEN 1
END) AS sale,
COUNT(pixel_count.id) AS PARTIAL,
(COUNT(pixel.id) - COUNT(pixel_count.id)) AS sales,
SUM(userdata.sendtry) AS Declines,
((COUNT(postbacktracker.id)/COUNT(pixel.id))*100) AS Cr,
SUM(postbacktracker.payout) AS Payout,
SUM(postbacktracker.payout)/COUNT(pixel.id) AS Epc
FROM campaign
LEFT JOIN pixel ON campaign.mkey = pixel.defa
LEFT JOIN products ON products.id = pixel.offer_id
LEFT JOIN team_users ON pixel.aff_id = team_users.hasoffersid
LEFT JOIN
(SELECT id,
userkey,
payout
FROM postbacktracker
GROUP BY userkey) postbacktracker ON pixel.transaction_id = postbacktracker.userkey
LEFT JOIN
(SELECT pixel.id,
COUNT(postbacktracker.id) AS conversions
FROM pixel
LEFT JOIN postbacktracker ON pixel.transaction_id = postbacktracker.userkey
GROUP BY pixel.id
HAVING conversions = 0) pixel_count ON pixel_count.id = pixel.id
LEFT JOIN
(SELECT userdata.id,
userdata.ukey,
userdata.sendtry,
COUNT(produktorder.id) AS orders,
SUM(produktorder.pvalue) AS pvalue_sum
FROM userdata
LEFT JOIN produktorder ON produktorder.nekp1stv1r = userdata.nekp1stv1r
GROUP BY userdata.id) userdata ON pixel.transaction_id = userdata.ukey
WHERE pixel.adddate >= 1527853697
AND pixel.adddate < 1531223297
GROUP BY campaign.id,
period
ORDER BY campaign.id,
pixel.adddate,
hour ;
问题出在这部分查询中(没有这个左联接查询是在0.0035秒内完成的。):
LEFT JOIN
(SELECT pixel.id,
COUNT(postbacktracker.id) AS conversions
FROM pixel
LEFT JOIN postbacktracker ON pixel.transaction_id = postbacktracker.userkey
GROUP BY pixel.id
HAVING conversions = 0) pixel_count ON pixel_count.id = pixel.id
此查询的正确构造的索引应如何显示?
这是解释结果:
1 PRIMARY pixel ALL index_defa,index_adddate 231 99.13 Using where; Using temporary; Using filesort
1 PRIMARY campaign ref index_mkey index_mkey 902 thanatos.pixel.defa 1 100.00 Using index
1 PRIMARY products eq_ref PRIMARY PRIMARY 4 thanatos.pixel.offer_id 1 100.00
1 PRIMARY team_users ref index_hasoffersid index_hasoffersid 4 thanatos.pixel.aff_id 1 100.00 Using index
1 PRIMARY <derived2> ref <auto_key0> <auto_key0> 902 thanatos.pixel.transaction_id 2 100.00
1 PRIMARY <derived3> ref <auto_key0> <auto_key0> 4 thanatos.pixel.id 10 100.00
3 DERIVED pixel ALL PRIMARY 231 100.00 Using temporary; Using filesort
3 DERIVED postbacktracker ref index_userkey index_userkey 902 thanatos.pixel.transaction_id 2 100.00
2 DERIVED postbacktracker ALL index_userkey 19 100.00 Using temporary; Using filesort
感谢帮助。
答案 0 :(得分:0)
那是一个非常奇怪的构造。我会简单地删除它。
为什么?
left join
,因此它不会过滤掉任何行。conversions
中的一个值未在查询中的任何地方使用。因此,join
似乎没有做任何有用的事情,您可以删除它。 (它有可能乘以行数,但是我猜这没有用。)
答案 1 :(得分:0)
首先,您不应该使用case循环这样的sql查询。请编写一个函数并调用它。您将看到,您的查询将比平常更快地返回。您的问题主要基于案例循环。因为您已经互相加入了很多表。您知道如何编写sql函数吗?
答案 2 :(得分:-1)
可以请您试试吗?这可能会让您烦恼。
SELECT pixel.id,
COUNT(postbacktracker.id) AS conversions INTO #pixel_count
FROM pixel
LEFT JOIN postbacktracker ON pixel.transaction_id = postbacktracker.userkey
GROUP BY pixel.id
HAVING conversions = 0
SELECT CONCAT(YEAR(FROM_UNIXTIME(pixel.adddate)), '/', MONTHNAME(FROM_UNIXTIME(pixel.adddate))) AS period,
CONCAT(HOUR(FROM_UNIXTIME(TRUNCATE(pixel.adddate / 3600, 0) * 3600)), ' - ', (HOUR(FROM_UNIXTIME(TRUNCATE(pixel.adddate / 3600, 0) * 3600)) + 1)) AS hour,
pixel.adddate AS adddate,
products.id AS OfferID,
products.name AS name,
campaign.id AS id,
campaign.mkey AS mkey
FROM campaign
LEFT JOIN pixel ON campaign.mkey = pixel.defa
AND pixel.adddate >= 1527832290
AND pixel.adddate < 1531201890
LEFT JOIN #pixel_count AS pixel_count ON pixel_count.id = pixel.id
LEFT JOIN products ON products.id = pixel.offer_id
LEFT JOIN team_users ON pixel.aff_id = team_users.hasoffersid
LEFT JOIN
(SELECT id,
userkey,
payout
FROM postbacktracker
GROUP BY userkey) postbacktracker ON pixel.transaction_id = postbacktracker.userkey
GROUP BY campaign.id,
period
ORDER BY campaign.id,
pixel.adddate,
hour ;