2

最近我有这个问题,一切正常,直到我将它发送到我在 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

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

好吧,看起来查询被锁定是由于其他类似的查询,处理了 650 万条记录,持续了 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
4

4 回答 4

1

你可以随时缓存它;-)

于 2010-07-28T15:35:14.620 回答
1

那么我要检查的第一件事是您在托管服务器上具有正确的索引。有时,人们在迁移数据库时忘记移动这些。

于 2010-07-28T15:34:43.527 回答
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

至少索引 JOIN 条件中使用的列(如果还没有的话)。

我看到一条关于查询运行 150 次的评论 - 你能详细说明一下吗?

于 2010-07-28T15:38:42.680 回答
0

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

他们描述问题的方式,甚至可能是针对从外部循环检查的每条记录测试内部循环,这将通过这种方法解决。虽然我认为 MySQL 会足够聪明,不会自己处理这个问题。

于 2010-07-28T15:37:58.357 回答