1

我真的对这两个查询感到困惑,它们的查询速度不稳定。这是我的两个表方案;

帖子表:(id、标题、日期等...)[日期索引]

关系表:(news_id,relation_id)[每行都有索引]

查询一:

SELECT *
FROM posts
WHERE id IN (
    SELECT news_id
    FROM relationships
    WHERE relation_id IN (?)
)
AND status = 1
ORDER BY `date` DESC

查询 B:

SELECT *
FROM posts AS p
INNER JOIN relationships AS r ON r.news_id = n.id
WHERE r.relation_id IN (?)
AND n.status = 1
ORDER BY n.date DESC

现在奇怪的部分是测试结果;首先尝试一个有30行的relation_id;

查询 A:总共 30 个,查询耗时 5.56 秒

查询 B:总共 30 个,查询耗时 0.03 秒

A 在较少行上速度较慢,B 在较少行上速度较快。接下来尝试一个有3k行的relation_id;

查询 A:总共 3,850 个,查询耗时 0.05 秒

查询 B:总共 3,850 个,查询耗时 0.70 秒

所以这让我很困惑,现在有更多的数据,A 更快了。最后一个,尝试使用 +10k 行的 multi relation_id;例子;relation_id IN (1, 2, 3, 4)

查询 A:总共 18,906 个,查询耗时 0.01 秒

查询 B:总共 18,906 个,查询耗时 3.34 秒

所以我该怎么做?查询 A 在很多行上速度很快,但在行数较少时速度很慢。对此查询还有其他真正的建议吗?(抱歉我的英语不好或语法错误)

编辑

这是 SQL EXPLAIN ;

查询 A 有 30 行 查询 A 有 30 行

具有 30 行的查询 B 查询 B

查询 A 有 18k 行 查询一个

具有 18k 行的查询 B 查询 b 2

4

1 回答 1

0

很奇怪,但那是 MySQL ;-)

优化器认为这status = 1是一个很强的限制。如果这成立,你会得到

select status=1, count(*) as num from posts group by status=1

如果你的表只有一小部分有,status=1那么从 mysqls 的角度来看,30 行解决方案仍然相当不错。

如果有很大一部分,status = 1那么您应该尝试使用查询

from posts ignore index (status) ...

或者

from posts force index (id) ...

执行解决方案中的位置。

您可以通过以下方式获得更多信息

explain select count(*) from relationships where relation_id in (1)

这显示了优化器根据它的索引统计信息期望的大小。

固定索引提示的问题在于它们是固定的。这意味着他们适用于好的和坏的场景。

有时临时表有助于避免这种情况,您可以将相关关系存储到其中。

于 2013-05-12T16:41:31.277 回答