5

在我的应用程序中,我有一个对某个主题的响应表。结构大致如下:

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

id是一个自动增量字段,topic_id并且author_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,依此类推。

两者之间的实际区别是什么?特别是。在许多同时用户的性能方面。

我在 PostgreSQL 中这样做,但我愿意切换到不同的 RDBMS。(我不想失去参照完整性,所以我不研究 NoSQL 解决方案)也许我必须调整数据库的一些参数(例如预取大小),以充分利用无界查询案例?

4

2 回答 2

3

我不能谈论 Postgres 的细节,但查询优化器可能会使用 LIMIT 子句作为各种不同执行计划成本计算的一部分。

如果你 ...

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

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

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

优化器可能假设您想要整个结果集,估计可能有几千行。

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

于 2012-11-08T17:55:48.027 回答
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;

只需在 WHERE 子句中添加 NOT IN 即可。

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

于 2012-11-08T17:45:36.070 回答