0

我有一个使用服务器端分页的简单查询。问题是 WHERE 子句调用昂贵的函数,而函数参数是用户输入,例如。用户正在搜索的内容。

SELECT 
  * 
FROM 
  ( SELECT /*+ FIRST_ROWS(numberOfRows) */ 
      query.*, 
      ROWNUM rn FROM 
        (SELECT            
            myColumns 
          FROM 
            myTable 
            WHERE expensiveFunction(:userInput)=1  
          ORDER BY id ASC
        ) query
    )
WHERE rn >= :startIndex 
AND ROWNUM <= :numberOfRows

假设 numberOfRows 很小,这很有效并且很快。但是我也想知道查询的总行数。根据用户输入和数据库大小,查询可能需要几分钟。我目前的方法是缓存这个值,但这仍然意味着用户需要等待几分钟才能看到第一个结果。

结果应该显示在 Jquery 数据表插件中,这对服务器端分页之类的事情有很大帮助。但是,它需要服务器返回总记录的值才能正确显示分页控件。

最好的方法是什么?(注:PHP)

我想如果立即用假的(估计会更好)行数返回第一页。加载页面后,对确定查询总行数的方法进行 ajax 调用(如果在此期间用户页面会发生什么情况?),然后更新伪造/估计的总行数。

但是我不知道如何进行估算。我用 SAMPLE (0.1) 尝试了 count(*) * 1000,但无论出于何种原因,它实际上比完整计数查询花费的时间更长。也只是返回一个假/随机值似乎也有点 hacky。它需要大于 1 个页面大小,以便启用“下一步”按钮。

其他想法?

4

2 回答 2

1

正如我在评论中所说,一种方法是使用“无数”方法。修改客户端脚本,使Next按钮始终处于启用状态并获取行,直到没有行,然后禁用该Next按钮。您始终可以添加一条通知消息,说明没有更多行,这样会更加用户友好。

考虑到您期望有大量记录,我怀疑用户是否会对所有结果进行分页。

另一种方法是安排一个 cron 作业,该作业将在后台对记录进行计数并将结果存储在一个名为totals. 作业的运行间隔应根据插入/删除的频率设置。

然后在前端,只需使用之前存储在totals. 它应该对数量进行适当的近似。

于 2012-09-26T11:57:12.080 回答
0

取决于您的数据库引擎。在 mysql 中,解决方案如下所示:

    mysql> SELECT SQL_CALC_FOUND_ROWS * FROM tbl_name
        -> WHERE id > 100 LIMIT 10;
    mysql> SELECT FOUND_ROWS();

基本上,您在您的选择(SQL_CALC_FOUND_ROWS)上添加另一个属性,它告诉 mysql 在执行查询时对行进行计数,就好像限制子句不存在一样,而 FOUND_ROWS 实际上检索该数字。

对于 oracle,请参阅这篇文章: 如何在 oracle 中执行此查询

其他 DBMS 可能有类似的东西,但我不知道。

于 2012-09-26T11:40:46.747 回答