这取决于您的数据库引擎(即哪种 SQL),但几乎每种 SQL 风格都支持对查询进行分页。
例如,MySQL 有LIMIT,MS SQL 有ROW_NUMBER。
因此,您像往常一样构建 SQL,然后只需添加特定于数据库引擎的分页内容,服务器就会自动返回查询结果的第 10 到 20 行。
编辑:
所以最终查询(选择返回给用户的数据)从一些表(临时或非临时)中选择数据,正如我预期的那样。
这是一个 SELECT 查询,您可以在 MySQL 中使用 LIMIT 进行分页。
在我看来,您的描述好像实际计算比将结果返回给用户的最终查询更占用资源。
所以我会做以下事情:
- 为输入的单词获取单独的结果表,并将它们保存在一个表中,以便您以后可以获取此特定查询的数据(例如,使用附加列,如 SessionID 或 QueryID)。这里没有分页。
- 再次查询这些结果表以获得返回给用户的最终查询。
您可以在此处使用LIMIT进行分页。
因此,当用户“启动”查询时,您只需执行一次实际计算(占用资源的查询)。然后,您只需从已填充的结果表中进行选择,即可将分页结果返回给用户。
编辑 2:
我刚刚看到您接受了我的回答,但是,这里有更多关于我使用“临时”表的详细信息。
当然,这只是一种可能的方法。如果预期结果不是太大,则将整个结果集返回给客户端,将其保存在内存中并执行分页客户端(如您所建议的那样)也是可能的。
但是,如果我们谈论的是真正的海量数据,而用户只会查看其中的一部分(想想 Google 搜索结果)和/或低带宽,那么您只想向客户端传输尽可能少的数据。
这就是我写这个答案时的想法。
所以:我不是指“真正的”临时表,而是指用于保存临时数据的“普通”表。
我在 MS SQL 方面比在 MySQL 方面更精通,所以我对 MySQL 中的临时表了解不多。
我可以告诉你我将如何在 MS SQL 中做到这一点,但也许在我不知道的 MySQL 中有更好的方法。
当我必须对资源密集型查询进行分页时,我想进行一次实际计算,将其保存在一个表中,然后从客户端多次查询该表(以避免对每个页面再次进行计算) .
问题是:在 MS SQL 中,临时表只存在于创建它的查询范围内。
所以我不能为此使用临时表,因为当我想第二次查询它时它会消失。
所以我使用“真实”的表格来处理类似的事情。
我不确定我是否正确理解了您的算法示例,所以我会稍微简化一下示例。无论如何,我希望我能把我的观点说清楚:
这是表(这可能不是有效的MySQL,只是为了展示概念):
create table AlgorithmTempTable
(
QueryID guid,
Rank float,
Value float
)
正如我之前所说的 - 它不是字面上的“临时”表,它实际上是一个真正的永久表,仅用于临时数据。
现在用户打开您的应用程序,输入他的搜索词并按下“搜索”按钮。
然后你启动你的资源密集型算法计算一次结果,并将其存储在表中:
insert into AlgorithmTempTable (QueryID, Rank, Value)
select '12345678-9012-3456789', foo, bar
from Whatever
insert into AlgorithmTempTable (QueryID, Rank, Value)
select '12345678-9012-3456789', foo2, bar2
from SomewhereElse
客户必须知道 Guid。也许您可以为此使用客户端的 SessionID(如果他有一个并且他不能一次启动多个查询......或者每次用户按下“搜索”按钮时,您都会在客户端上生成一个新的 Guid,或其他)。
现在所有的计算都完成了,结果的排名列表保存在表格中。
现在您可以查询表,按 QueryID 过滤:
select Rank, Value
from AlgorithmTempTable
where QueryID = '12345678-9012-3456789'
order by Rank
limit 0, 10
由于 QueryID,多个用户可以同时执行此操作,而不会干扰彼此的查询。如果您为每个搜索创建一个新的 QueryID,同一个用户甚至可以同时运行多个查询。
现在只剩下一件事要做:删除不再需要的临时数据(仅删除数据!永远不会删除该表)。
因此,如果用户关闭查询屏幕:
delete
from AlgorithmTempTable
where QueryID = '12345678-9012-3456789'
不过,这在某些情况下并不理想。如果应用程序崩溃,数据将永远保留在表中。
有几种更好的方法。哪一个最适合您取决于您的应用程序。一些可能性:
- 您可以添加一个以当前时间为默认值的日期时间列,然后运行每晚(或每周)的作业,删除早于 X 的所有内容
- 与上述相同,但您可以在每次有人开始新查询时删除早于 X 的所有内容,而不是每周作业
- 如果每个用户都有一个会话,则可以将 SessionID 保存在表的附加列中。当用户注销或会话到期时,您可以删除表中具有该 SessionID 的所有内容