2012-11-08 34 views
4

在我的应用程序中,我有一个主题回复表。其结构大致如下:如何使用与简单获取N个结果不同的LIMIT子句?

CREATE TABLE responses (
    id INT NOT NULL PRIMARY KEY, 
    topic_id INT NOT NULL, 
    author_id INT NOT NULL, 
    response TEXT 
); 

id是一个自动递增字段,topic_idauthor_id外键,也有相应的指标等

我总是想通过插入时间订购,通常最近。在大多数情况下,我将通过topic_id进行过滤。一个典型的查询看起来是这样的:

SELECT * FROM responses WHERE topic_id=123 ORDER BY id DESC LIMIT 20; 
-- or, for pagination: 
SELECT * FROM responses WHERE topic_id=123 AND id < 456789 ORDER BY id DESC LIMIT 20; 

我想要实现阻止列表 - 每个用户有author_id就是他们不希望看到一个列表。我需要检索前20个结果,排除那些author_id s 以及回复他们的回复。确定一个行是否应该排除是非常复杂的,虽然它可能会在数据库中执行(PL/SQL或预处理),但我希望将逻辑保留在应用程序中。所以我可以做以下两件事之一:

  1. 忘记LIMIT子句,使查询不受限制。直到我计算了20个有效结果为止,然后关闭查询。
  2. 应用分块 - 指定LIMIT 40,并希望它足以获得20个“好”结果。如果不是,则取下40个等等。

这两者之间的实际区别是什么? ESP。在许多并发用户的性能方面。

我在PostgreSQL中这样做,但我愿意切换到不同的RDBMS。 (我不想失去引用完整性,所以我没有考虑NoSQL解决方案)也许我不得不调整数据库的某些参数(例如预取大小),以充分利用无界查询情况?

+0

这并不直接回答你的问题,但出于好奇,你的数据模型中定义了如何“回复他们的回复”?如果您真的关心性能,最好让数据库完成它的工作,并让索引工作来过滤数据。 –

+0

数据模型没有定义它 - 它涉及解析“reply”标签和用户名的响应文本。一行可以包含对多个其他行的回复,以及多个用户的提及。一行也可以是部分回复/回复和部分独立内容 - 在这种情况下,我想要做一些启发式猜测并隐藏部分或全部行。 我可以对此进行预处理并创建1:n响应 - 回复关系和1:n响应 - 关于提及的作者,这可能是一个足够好的数据模型。 – matejcik

+0

至于性能方面,现在“分块”方法已经足够好了,我主要想知道在性能和便利性方面取消LIMIT子句是否是一个很好的折衷。 – matejcik

回答

1

在SQL中添加块列表并不困难。

SELECT * FROM responses 
WHERE topic_id=123 
    AND author_id NOT IN (SELECT author_id FROM blocked WHERE user_id = X) 
ORDER BY id DESC LIMIT 20; 

只需添加一个NOT IN到您的WHERE子句。

如果你有一些理由,你不能做到这一点,那么你的大块的想法是最好的。您不希望没有限制,因为那么数据库会将所有内容都返回给查询它的客户端或服务器。

3

我不能说Postgres的具体情况,但查询优化器可能会使用LIMIT子句作为各种不同执行计划的成本计算的一部分。

如果您...

select ... from ... where ... limit n 

那么优化器知道你只是要检索n行,但...

select ... from ... where ... 

优化器可能会认为你想要的整个结果集,可能估计有几千行。

特别是我期望RDBMS支持应用LIMIT子句的基于索引的访问方法。

相关问题