简体   繁体   English

简单的MySQL查询运行速度很慢

[英]Simple MySQL query runs very slow

I found some strange(for me) behavour in MySQL. 我在MySQL中发现了一些奇怪的(对我来说)行为。 I have a simple query: 我有一个简单的查询:

SELECT CONVERT( `text`.`old_text` 
USING utf8 ) AS stext
FROM  `text` 
WHERE  `text`.`old_id` IN 
(    
 SELECT  `revision`.`rev_text_id`
 FROM  `revision` 
 WHERE  `revision`.`rev_id`
 IN 
  (    
  SELECT `page_latest`
  FROM  `page` 
  WHERE `page_id` = 108
  )
)

when i run it, phpmyadmin show execution time of 77.0446 seconds. 当我运行它时,phpmyadmin显示执行时间为77.0446秒。
But then i replace 但后来我换了

WHERE  `text`.`old_id` IN 

by 通过

WHERE  `text`.`old_id` = 

it's execution time falls to about 0.001 sec. 它的执行时间降至约0.001秒。 Result of this query 此查询的结果

 SELECT  `revision`.`rev_text_id`
 FROM  `revision` 
 WHERE  `revision`.`rev_id`
 IN 
  (    
  SELECT `page_latest`
  FROM  `page` 
  WHERE `page_id` = 108
  )    

is

+------------+
|rev_text_id |
+------------+
|6506        |
+------------+

Can somebody please explain this behavour? 有人可以解释一下这种行为吗?

try to add INDEX on the following columns, 尝试在以下列上添加INDEX

ALTER TABLE `text` ADD INDEX idx_text (old_id);
ALTER TABLE `revision` ADD INDEX idx_revision (rev_text_id);

and Execute the following query 并执行以下查询

SELECT  DISTINCT CONVERT(a.`old_text` USING utf8 ) AS stext
FROM    `text` a
        INNER JOIN `revision` b
            ON a.`old_id` = b.`rev_text_id`
        INNER JOIN `page` c
            ON b.`rev_id` = c.`page_latest`
WHERE   c.`page_id` = 108

PS: Can you run also the following query and post their respective results? PS:您还可以运行以下查询并发布各自的结果吗?

DESC `text`;
DESC `revision`;
DESC `page`;

MySQLDB is looping through each result of the inner query and comparing it with each record in the outer query. MySQLDB循环遍历内部查询的每个结果,并将其与外部查询中的每个记录进行比较。 in the second inner query; 在第二个内部查询中;

   WHERE  `revision`.`rev_id`
   IN 
   ( SELECT `page_latest`
     FROM  `page` 
     WHERE `page_id` = 108

you should definitely use '=' instead of IN, since you're selecting a distinct record, there would be no point in looping through a result when you know only one record will be returned each time 你应该使用'='代替IN,因为你选择了一个不同的记录,当你知道每次只返回一条记录时,循环结果就没有意义了

There are two primary ways you can increase your query performance here 您可以通过两种主要方式提高查询效果

  • Add Indexes (such as Kuya mentioned) 添加索引(如Kuya提到的)
  • Rid yourself of the subqueries where possible 在可能的情况下摆脱子查询

For Indexes, add an index on the columns you are searching for your matches: text.old_id, revision.rev_text_id & page.page_id 对于索引,在要搜索匹配项的列上添加索引:text.old_id,revision.rev_text_id&page.page_id

ALTER TABLE `text` ADD INDEX idx_text (old_id);
ALTER TABLE `revision` ADD INDEX idx_revision (rev_text_id);
ALTER TABLE `page` ADD INDEX idx_page (page_id);

Your next issue is that nested-sub-selects are hell on your query execution plan. 您的下一个问题是嵌套子选择是您的查询执行计划的地狱。 Here is a good thread discussing JOIN vs Subquery . 这是一个讨论JOIN和Subquery的好主题。 Here is an article on how to get execution plan info from mySQL. 这是一篇关于如何从mySQL 获取执行计划信息的文章。

First looks at an execution plan can be confusing, but it will be your best friend when you have to concern yourself with query optimization. 首先看一下执行计划可能会令人困惑,但是当你不得不关注查询优化时,它将成为你最好的朋友。

Here is an example of your same query with just joins ( you could use inner or left and get pretty much the same result). 下面是一个只使用连接的相同查询的示例(您可以使用内部或左侧,并获得几乎相同的结果)。 I don't have your tables or data, so forgive synax issues (there is no way I can verify the code works verbatim in your environment, but it should give you a good starting point). 我没有你的表或数据,所以原谅synax问题(我无法在你的环境中逐字验证代码,但它应该给你一个很好的起点)。

SELECT 
  CONVERT( `text`.`old_text` USING utf8 ) AS stext
  FROM  `text` 
  -- inner join only returns rows when it can find a 
  --    matching `revision`.`rev_text_id` row to `text`.`old_id`
  INNER JOIN `revision`  
  ON `text`.`old_id` = `revision`.`rev_text_id` 
  -- Inner Join only returns rows  when it can find a 
  --  matching `page_latest` row to `page_latest`
  INNER JOIN `page`
  ON `revision`.`rev_id` = `page`.`page_latest`
WHERE `page`.`page_id` = 108

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM