假设我有一张这样的表:
CREATE TABLE book (
id INTEGER PRIMARY KEY,
title VARCHAR(32) NOT NULL
);
我希望支持带偏移量的查询,以支持返回图书清单的API,按照非唯一标题字段排序并给定偏移和限制。
这里的问题是为非唯一title
列定义唯一索引(或辅助列或类似内容)的最有效方法[1],该列可用作不透明偏移标记查询我正在使用的ORDER BY title
。我想过在函数上创建的索引会返回行的唯一数字位置,但我担心这会严重影响大表的INSERT和UPDATE的时序,我认为有一个最佳的解决方案。
虽然这对于ORDER BY {unique_field}
查询来说很简单[2]但我看不到为非唯一字段实现相同的简单方法。
另外我们假设解决方案应该在postgresql和mysql中运行。
注意:
[1]由于直接的解决方案,如SELECT id,title FROM book ORDER BY title OFFSET [number] LIMIT [number]对于大数值偏移值的工作非常糟糕,我会介绍一些代表偏移量的不透明令牌我的API中的给定集合用于获取图书块。
因此API方法将返回按标题排序并具有给定偏移量的书籍列表,如下所示(伪代码):
BookPage getBooks(optional string offsetToken, int limit)
其中BookPage定义如下:
class BookPage {
nonnull List<Book> books;
nonnull string offsetToken; // expected to be used to return a next page
}
使用示例,书籍表包含2 * N本书:
// 1st call
BookPage page1 = getBooks(null, 2); // get first 2 books
BookPage page2 = getBooks(page1.offsetToken, 2); // get next 2 books
BookPage page3 = getBooks(page2.offsetToken, 2); // get next 2 books
//...
BookPage pageN = getBooks(pageN-1.offsetToken, 2); // get last 2 books
和列表的串联page1.books,page2.books,... pageN.books将生成按标题按升序排序的书籍列表。
[2]例如:如果getBooks API将使用偏移查询,其中按id(这是主键)offsetToken排序的书籍将是最后一本书的id,getBooks API的实现将如下所示(伪代码):
BookPage getBook(optional string offsetToken, int limit) {
Long startId = (offsetToken != null ? toLong(offsetToken) : null);
page.books = (SELECT id, title FROM books
WHERE :startId IS null OR id>:startId
ORDER BY id
LIMIT :limit);
page.offsetToken = toString(lastElementOf(page.books).id)
return page;
}
答案 0 :(得分:0)
到目前为止,我发现的最简单,最简单的解决方案是将非唯一列与主键结合使用。它使选择的查询稍微复杂化 - 例如对于原始问题,你需要写一些类似(title =:title AND id&gt;:id)OR(title&gt;:title),其中:title和:id构成offsetToken(最后一项的标题和id)。