我的MySQL查询时间很糟糕。我已经度过了周末的大部分时间,今天的大部分时间都在尝试使这个查询运行得更快一些。我的速度要快得多,但我知道我可以做得更好。
SELECT m.id,other_fields,C.contacts_count FROM marketingDatabase AS m
LEFT OUTER JOIN
(SELECT COUNT(*) as contacts_count, rid
FROM contacts
WHERE status = 'Active' AND install_id = 'XXXX' GROUP BY rid) as C
ON C.rid = m.id
WHERE (RAND()*2612<50)
AND do_not_call != 'true'
AND `ACTUAL SALES VOLUME` >= '800000'
AND `ACTUAL SALES VOLUME` <= '1200000'
AND status = 'Pending'
AND install_id = 'XXXXX'
ORDER BY RAND()
我有'install_id','category'和'status'的索引,但EXPLAIN显示它是基于9100行进行排序。
我的解释在这里: https://s3.amazonaws.com/jas-so-question/Screen+Shot+2012-03-13+at+12.34.04+AM.png
有人建议我能做些什么来加快速度吗?查询的整个要点是从帐户的记录(install_id)中选择一个随机记录,该记录与销售量,状态和do_not_call等特定条件相匹配。我目前正在收集25条记录并对其进行缓存(使用PHP),因此我每25次请求只需运行一次此查询,但我已经处理了每天数千条请求。它目前需要0.2秒才能运行。我意识到通过使用ORDER BY RAND()我已经取得了重大的性能提升,但它只是排序了25行。
提前感谢您的帮助。
**编辑:我忘了提及'contact_sort'索引在'contacts'表上,并索引install_id,status和rid。 (在marketingDatabase中删除引用记录ID,以便它知道联系人所属的记录。
**编辑2:查询中的2612数字表示marketingDatabase中符合条件(install_id,status,实际销售量等)的行数。
答案 0 :(得分:1)
由于我没有看到您的索引定义,我不确定它们是否正确。该查询将受益于以下索引:
contacts
上的复合索引(install_id,status,rid)
marketingDatabase
上的综合索引(install_id,status,`ACTUAL SALES VOLUME`)
答案 1 :(得分:0)
我玩了几个查询,我认为你永远不会得到索引查询来使用RAND(),特别是当你在WHERE子句和ORDER中使用它时BY子句。如果可能的话,我会在PHP逻辑中引入随机元素,并且可能会看两个简单的查询是否比一个相当复杂的查询更有意义。除此之外,您在随机结果集上有LEFT OUTER JOIN,这也可能会增加必须完成的工作量。
总之,我的猜测是 - 重写以排除RAND,看看你是否可以摆脱LEFT OUTER JOIN。两个简单的索引查询,中间有一点PHP可能会好很多。