1

我的问题是概念性的,但对我来说非常重要:

使用数据库时,您通常会从包含结果集的查询中获取迭代器。但是:当您想要进行分页时,您希望能够来回移动该结果集。然而,这是不可能使用迭代器的。所以这里的幼稚想法是使用转换来列出。但这又需要花费 O(n) 的时间,这可能会导致严重的性能问题。

我确定这个问题必须有解决方案(除了使用弹性搜索:D)。解决这个问题的最佳方法是什么?

最诚挚的问候,

斯特凡

4

1 回答 1

1

您想要分页,但不想将未O(n)分页的结果集加载到内存中。足够公平 - 从逻辑上讲,这意味着数据库必须将分页块交给您。我认为大多数 RDMS 数据库都有类似“LIMIT”和“OFFSET”的 SQL:

select id, name from foo where date > ? LIMIT $start, $page_size;

如果您正在处理 MySQL,并且正在编写原始 SQL,那么它将是这样的。但是对于像 Slick 这样的库,你可以

val query = for { 
  d <- Parameter[Date]
  f <- foo if f.date > d
} yield (f.id, f.name)

所以要让所有行取消分页,你要做

query(yesterday).list
// Select id, name from foo

如果你想要分页,这很简单:

query(yesterday).drop(20).take(5).list
// Select id, name from foo limit 20, 5 ; %% whatever; I suck at SQL and can't remember syntac

                                          %% but you get the point.

(Id, Name)假设您每页只需要 5 个元素,它将返回 5 个元素的列表。这意味着该子序列将是结果的第 5 页。

并不是说如果您在内存中query(yesterday)没有 a Listof 结果,您可能会这样做:SLICK 为您提供了查询的抽象,一种Query包含许多通常在集合中找到的有用方法的类型。该.list方法实际上是执行最终查询以获取您的结果List[T](在此示例中List[(Int, String)]),但在调用它之前,您可以“分页”您的结果(通过调用.takedrop来构建原始查询),在此示例中,SQL 执行为您分页,SLICK 会生成该 SQL,因此您只需执行.take.drop其他任何操作。

如果您的模型层利用 SLICK 的可组合性会有所帮助:您在 SLICK 中定义基本查询而不是编写原始 SQL,并且这些查询可用作其他查询的构建块。

于 2013-10-16T18:08:05.530 回答