如何使这个mysql查询更高效,运行更快?

时间:2015-01-19 00:02:37

标签: mysql sql performance time time-complexity

这是我的mysql查询(3个嵌套的Select语句):

SELECT * FROM emotions 
WHERE 
( randomid IN 
     ( 
           SELECT idpost 
           FROM p_n_relation 
           WHERE idnetwork IN 
           (
                 SELECT id 
                 FROM networks 
                 WHERE name = 'Babblenow' 
                       AND isActive = 1 
                       AND isDeleted = 0
          ) 
       AND isActive = 1 AND isDeleted = 0 
   )   AND isActive = 1 
       AND isDeleted =0 
       AND onid = '0' AND type = 0 
)ORDER BY rating DESC

每个表格情感,p_n_relations和网络包含大约10k行。
执行此查询需要30秒以上的时间并在服务器运行时挂起服务器! 有没有更有效的方法来做我想做的事情?大公司如何在几秒钟内完成这项工作?

编辑 - 要完全:
p_n_relations : 5774networks : 9emotions : 427中的行数 这是Query took 125.6770 sec

我的数据库结构:
情绪表,网络表,P_n_relation表按顺序排列。
http://imgur.com/bmEEavH,d3iE6Lg,twXMWU9

2 个答案:

答案 0 :(得分:3)

试试这个:

SELECT emotions.* FROM emotions
LEFT JOIN p_n_relation ON (p_n_relation.idpost = emotions.randomid)
LEFT JOIN networks ON (networks.id = p_n_relation.idnetwork)
WHERE 
(networks.name='Babblenow') AND (networks.isActive = 1) AND (networks.isDeleted = 0) AND
(p_n_relation.isActive = 1) AND (p_n_relation.isDeleted = 0) AND
(emotions.isActive = 1) AND (emotions.isDeleted = 0) AND (emotions.onid = '0') AND (emotions.type = 0)
ORDER BY emotions.rating DESC

根据您发布的表格结构,我建议对emotion.randomid和p_n_relation.idpost(现在为varchar(40)和varchar(50))使用相同的字段类型。除此之外,还有关于emotion.randomid,p_n_relation.idpost,networks.id和p_n_relation.idnetwork的指示。正如其他人建议尝试在networks.name上制作索引。之后,尝试逐步构建查询。

首先,从情绪中选择情绪。但不要在哪里使用并测量时间。它应该很快,如果不是你的MySQL配置有一些很大的问题。

SELECT emotions.* FROM emotions;

如果它很快,请加入p_n_relation,但不要使用where。

SELECT emotions.*, p_n_relation.* FROM emotions
LEFT JOIN p_n_relation ON (p_n_relation.idpost = emotions.randomid);

如果你有正确的索引,它也应该快。如果没有,请尝试解析它:

EXPLAIN SELECT emotions.*, p_n_relation.* FROM emotions
LEFT JOIN p_n_relation ON (p_n_relation.idpost = emotions.randomid);

您可以阅读有关EXPLAIN输出的here,但您也可以将其发布到您的问题中。

因此,如果它仍然很快,请加入第3个表格:

SELECT emotions.*, p_n_relation.* FROM emotions
LEFT JOIN p_n_relation ON (p_n_relation.idpost = emotions.randomid)
LEFT JOIN networks ON (networks.id = p_n_relation.idnetwork);

测试,测量,然后开始逐步包含WHERE部分。如果某个地方性能下降,你应该调查它(可能是一个错误的或缺少的索引,字段类型,或MySQL本身可能导致问题)。

答案 1 :(得分:0)

转换为连接,反转连接顺序:

SELECT DISTINCT e.*
FROM networks n
JOIN p_n_relation r ON r.idnetwork = n.id
JOIN emotions e ON e.randomid = r.idpost
WHERE n.name = 'Babblenow' 
AND n.isActive = 1 
AND n.isDeleted = 0

此表顺序是最佳的,因为您的条件都在网络表上。优化器假定来识别它并自动更改连接顺序,但我通过经验发现优化器可能很密集。

创建索引(如果它们尚不存在):

create index networks_name on networks(name);
create index  p_n_relation_idnetwork on (p_n_relation(idnetwork);