2010-07-28 132 views
2

最近我有这个question,一切正常,直到我把它发送到我的服务器在DreamHost。如何提高此查询的性能?

下面的查询似乎需要太长的时间来执行,我不知道为什么这么多行一次处理。在我的本地服务器中,相同的查询在0.3秒内执行完毕。

SELECT feed_entries . * 
FROM feed_entries 
WHERE 
id 
IN (

SELECT e.id 
FROM feed_entries AS e 
INNER JOIN feeds AS f ON e.feed_id = f.id 
INNER JOIN entries_categorias AS ec ON ec.entry_id = e.id 
INNER JOIN categorias AS c ON ec.categoria_id = c.id 
WHERE 
e.deleted =0 
AND 
c.slug 
IN ('entenda', 'google') 
GROUP BY e.id 
HAVING COUNT(DISTINCT ec.id) =2 

) 
ORDER BY date DESC 
LIMIT 1 

这是我从支持团队收到的消息:

嗯,它看起来像该查询 锁定由于这些其他查询 像这样的加工6.5百万 记录,持续11秒。

# Query_time: 11.639269 Lock_time: 0.000192 Rows_sent: 2 Rows_examined: 
6509098 
use desenvolvimentistas; 
SET timestamp=1280325753; 
SELECT `e`.*, `f`.`titulo` AS `feedTitulo`, `f`.`url` AS `feedUrl` FROM 
`feed_entries` AS `e` 
INNER JOIN `feeds` AS `f` ON e.feed_id =f.id WHERE (e.id IN (SELECT 
`e`.`id` FROM `feed_entries` AS `e` 
INNER JOIN `feeds` AS `f` ON e.feed_id =f.id 
INNER JOIN `entries_categorias` AS `ec` ON ec.entry_id =e.id 
INNER JOIN `categorias` AS `c` ON ec.categoria_id =c.id WHERE (e.deleted 
=0) AND (e.id NOT IN ('', '', '842', '853', '774', '878')) AND 
(e.imagem145x145 =1) AND (c.slug IN('destaque-2')) GROUP BY `e`.`id` 
HAVING (COUNT(DISTINCT ec.id) =1))) ORDER BY `e`.`date` DESC LIMIT 4; 

有可能的查询需要在本地计算机是 空闲的0.3秒到 运行,但因为它是在 一次运行查询150这是在我们的服务器上 缓慢,并且每一个正在处理 1530万条记录。

我有我们的MySQL管理员看了看 它,他说,这是相当低效 和感到惊讶的是 数据库甚至访问,因为 查询没有这么锁定。他说 表示数据库将被禁用,如果 它继续这种方式并导致 服务器问题。他说你应该修复所检查的行或者获得一个MySQL PS,尽管mysql ps不会修复 它,而是只会阻止 数据库被禁用。

下面是该查询:

# Query_time: 25.944779 Lock_time: 0.000176 Rows_sent: 0 Rows_examined: 
15378209 
use desenvolvimentistas; 
SELECT `feed_entries`.* FROM `feed_entries` WHERE (id IN (SELECT `e`.`id` 
FROM `feed_entries` AS `e` INNER JOIN `feeds` AS `f` ON e.feed_id =f.id 
INNER JOIN `entries_categorias` AS `ec` ON ec.entry_id =e.id INNER JOIN 
`categorias` AS `c` ON ec.categoria_id =c.id WHERE (e.deleted =0) AND 
(c.slug IN('entenda','google')) GROUP BY `e`.`id` HAVING (COUNT(DISTINCT 
ec.id) =2))) ORDER BY `date` DESC LIMIT 1; 

这里是另一个需要被固定:

# Query_time: 27.010857 Lock_time: 0.000165 Rows_sent: 0 Rows_examined: 
15382750 
use desenvolvimentistas; 
SET timestamp=1280325706; 
SELECT `e`.*, `f`.`titulo` AS `feedTitulo`, `f`.`url` AS `feedUrl` FROM 
`feed_entries` AS `e` 
INNER JOIN `feeds` AS `f` ON e.feed_id =f.id WHERE (e.id IN (SELECT 
`e`.`id` FROM `feed_entries` AS `e` 
INNER JOIN `feeds` AS `f` ON e.feed_id =f.id 
INNER JOIN `entries_categorias` AS `ec` ON ec.entry_id =e.id 
INNER JOIN `categorias` AS `c` ON ec.categoria_id =c.id WHERE (e.deleted 
=0) AND (c.slug IN('manchete', 'google')) GROUP BY `e`.`id` HAVING 
(COUNT(DISTINCT ec.id) =2))) ORDER BY `e`.`date` DESC LIMIT 4;7:18 

回答

1

理想情况下,每个问题的一个查询请 - 您可以询问的问题数量没有限制,并且可以最大限度地减少与每个单独查询相关的颤音。

我重新写你的第一个查询为:

SELECT t.* 
    FROM feed_entries t 
    WHERE EXISTS(SELECT NULL 
        FROM feed_entries AS e 
        JOIN feeds AS f ON e.feed_id = f.id 
        JOIN entries_categorias AS ec ON ec.entry_id = e.id 
        JOIN categorias AS c ON ec.categoria_id = c.id 
       WHERE e.deleted = 0 
        AND c.slug IN ('entenda', 'google') 
        AND e.id = t.id 
       GROUP BY e.id 
       HAVING COUNT(DISTINCT ec.id) = 2) 
ORDER BY date DESC 
    LIMIT 1 

指数在连接标准使用的列在最低限度,如果没有的话。

我看到一条关于正在运行的查询的150条评论 - 您能否详细说明一下?

+0

因为他命令它,但只取得最好的结果,是否有一个好的建议可以有'日期'的索引? – 2010-07-28 15:44:54

+0

@Neil Trodden:是的,但是[MySQL对分配索引的空间有限制(MyISAM为1,000,InnoDB为767)](http://dev.mysql.com/doc/refman/5.0/en/create-index .html)所以JOIN标准是我的首要任务,然后看看我能做些什么来覆盖索引。 – 2010-07-28 15:59:19

+0

谢谢,我减少了150个查询的数量并定义了索引。也发现了其他的错误。现在可以了。 – 2010-08-03 16:12:23

1

嗯,我会检查的第一件事是,你有托管服务器上的正确索引。有时候,人们在迁移数据库时会忘记移动它们。

1

你总是可以缓存它;-)

+0

我已经有缓存。但是这个错误需要修正,我的表格不超过一千行。他说有一个查询处理了一千五百万个数据。 – 2010-07-28 16:34:22

0

我会尝试创建一个查询从内一个。 然后将生成的id手动添加到外部(其中((1,2,3,4,5)中的id))。 尽管这不会自动提高性能,但至少知道发生了什么。

他们描述问题的方式,甚至可能是内循环针对从外循环检查的每个单个记录进行测试,这将通过该方法来修复。尽管我认为MySQL会很聪明,但不能自行处理。