2011-10-26 22 views
1

我有这样大的查询,我不能完全重建,因为客户的应用:MySQL的加入优化大查询

SELECT count(AdvertLog.id) as count,AdvertLog.advert,AdvertLog.ut_fut_tstamp_dmy as day, 
      AdvertLog.operation, 
      Advert.allow_clicks, 
      Advert.slogan as name, 
      AdvertLog.log, 
         (User.tx_reality_credit 
      +-20 
      -(SELECT COUNT(advert_log.id) FROM advert_log WHERE ut_fut_tstamp_dmy <= day AND operation = 0 AND advert IN (168)) 
      +(SELECT IF(ISNULL(SUM(log)),0,SUM(log)) FROM advert_log WHERE ut_fut_tstamp_dmy <= day AND operation IN (1, 2) AND advert = 40341)) AS points 
FROM `advert_log` AS AdvertLog 
LEFT JOIN `tx_reality_advert` Advert ON Advert.uid = AdvertLog.advert 
LEFT JOIN `fe_users` AS User ON (User.uid = Advert.user or User.uid = AdvertLog.advert) 
WHERE User.uid = 40341 and AdvertLog.id>0 
GROUP BY AdvertLog.ut_fut_tstamp_dmy, AdvertLog.advert 
ORDER BY AdvertLog.ut_fut_tstamp_dmy_12 DESC,AdvertLog.operation,count DESC,name 
LIMIT 0, 15 

它需要大约1.5秒是太长。

指标:

User.uid 
AdvertLog.advert 
AdvertLog.operation 
AdvertLog.advert 
AdvertLog.ut_fut_tstamp_dmy 
AdvertLog.id 
Advert.user 
AdvertLog.log 

的输出解释:

id select_type table type possible_keys key key_len ref rows Extra 
1  PRIMARY User const PRIMARY PRIMARY 4  const 1  Using temporary; Using filesort 
1  PRIMARY AdvertLog range PRIMARY,advert PRIMARY 4 NULL 21427 Using where 
1  PRIMARY Advert eq_ref PRIMARY PRIMARY 4 etrend.AdvertLog.advert 1 Using where 
3 DEPENDENT SUBQUERY advert_log ref ut_fut_tstamp_dmy,operation,advert advert 5 const 1 Using where 
2 DEPENDENT SUBQUERY advert_log index_merge ut_fut_tstamp_dmy,operation,advert advert,operation 5,2 NULL 222 Using intersect(advert,operation); Using where 

谁能帮助我,因为我尝试不同的事情,但没有改善

+0

有没有指数' Advert.uid'? (顺便说一下,提供关键/ EXPLAIN信息的蝙蝠道具。) – Wiseguy

回答

0

查询是相当大的,而且我d预计这需要花费相当多的时间,但如果不存在,您可以尝试在Advert.uid上添加索引。除此之外,拥有比我更好的SQL-foo的人将不得不回答这个问题。

+0

是的,Advert.uid有索引 – anjalis

0

首先,您的WHERE子句基于特定的“User.ID”,但广告(用户ID)在Advert_Log上有一个索引。因此,首先,改变WHERE子句来反映这个...

Where 
    AdverLog.Advert = 40341 

然后,去掉“LEFT JOIN”,只是一个“加入”到用户表。

最后(不查询的全部重写),我会钉在“STRAIGHT_JOIN”关键字...

select STRAIGHT_JOIN 
    ... rest of query ... 

告诉执行的顺序查询优化器/关系明确说明。

另一个需要优化的领域是预先查询“点数”(基于广告和操作的计数和日志)一次,然后从该查询中抽取答案(作为子查询),而不是通过两个查询运行。但我有兴趣知道上面的WHERE,JOIN和STRAIGHT_JOIN有什么影响。

此外,基于以下方式查看与用户表的连接:Advert_Log.Advert(userID)或TX_Reality_Credit.User(自从Advert_Log和TX_Reality_Credit之间的连接后看起来不相同的另一个用户ID TRC)基于TRC.UID),除非这是一个不正确的假设。这可能会导致错误的结果,因为您正在测试多个用户ID ...广告用户,以及谁是“TRC”表中的“用户”......这将导致哪些用户的信用被应用于“分”计算。

为了更好地理解关系和背景,你可以提供一些更清楚地了解从Advert_Log到TX_Reality_Credit角度来看,这些表中,和广告VS UID VS用户...

+0

嗨,感谢您提出有趣的建议,我会尝试他们在工作的早晨解释用户混乱,创建的人该应用程序设计它非常糟糕,我不知道什么地方的原因,但解释: – anjalis

+0

在广告表中有广告与用户字段(广告的所有者)作为外键和AdvertLog正在写点击广告,也是当用户是购买新的信用。点击是操作字段中的数字1,2并且购买信用为0.这是问题,因为当有人点击广告时,它将写入广告的AdvertLog.advert ID,但是如果用户购买信用它写入AdvertLog。广告用户ID(广告的所有者),这就是为什么加入用户到两个表 – anjalis

+0

@ user1014954,这导致我回到我的问题内容......应该使用哪个用户作为tx_reality_credit的基础。你应该提供一些示例数据来显示每张表格中的一些内容(如果适用,请提供示例名称),这样我们就可以更好地了解你们之间的关系以及这些元素将与什么对抗...... – DRapp