【发布时间】:2015-06-14 09:27:03
【问题描述】:
假设我有一张这样的桌子:
CREATE TABLE book (
id INTEGER PRIMARY KEY,
title VARCHAR(32) NOT NULL
);
我想支持带偏移量的查询,以支持返回书籍列表的 API,按 non-unique 具有给定偏移量和限制的标题字段排序。
这里的问题是什么是最有效的方法 [1] 为非唯一的 title 列定义唯一索引(或辅助列或类似的东西)可以用作查询中的不透明偏移标记我正在使用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
}
示例使用,book table 包含 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;
}
【问题讨论】: