Evi*_*ter 58 php sql postgresql window-functions sql-limit
分页来自数据库的数据时,您需要知道将有多少页面呈现页面跳转控件.
目前我通过运行查询两次,一次包装count()以确定总结果,第二次应用限制以获取当前页面所需的结果.
这似乎效率低下.有没有更好的方法来确定在LIMIT应用之前会返回多少结果?
我正在使用PHP和Postgres.
Erw*_*ter 120
自2008年以来情况发生了变化.您可以使用窗口函数在一个查询中获取完整计数和有限结果.(2009年推出PostgreSQL 8.4).
SELECT foo
, count(*) OVER() AS full_count
FROM bar
WHERE <some condition>
ORDER BY <some col>
LIMIT <pagesize>
OFFSET <offset>;Run Code Online (Sandbox Code Playgroud)
请注意,这可能比没有总数更昂贵.必须对所有行进行计数,并且仅使用匹配索引中的顶行可能的快捷方式可能不再有用.
与小表或full_count<= OFFSET+ 无关LIMIT.事情要大得多full_count.
OFFSET极端情况:当至少与基本查询中的行数一样大时,不返回任何行.所以你也没有full_count.可能的选择:
考虑一系列事件:
SELECT子句(和WHERE条件,但不是这里)过滤基表中的限定行.
(JOIN和聚合函数会在这里.)
考虑所有符合条件的行(取决于GROUP BY函数的子句和框架规范),应用窗口函数.简单SELECT基于所有行.
OVER
(count(*) OVER()或者ORDER BY会去这里.)
DISTINCT/ DISTINCT ON根据建立的顺序应用,以选择要返回的行.
LIMIT/ OFFSET表中的行数越来越多,效率越来越低.如果您需要更好的性能,请考虑其他方法
有完全不同的方法来获得受影响的行数(不完整的计数之前LIMIT与OFFSET被应用).Postgres具有内部簿记,受上一个SQL命令影响的行数.有些客户端可以访问该信息或自行计数行(如psql).
例如,您可以在执行SQL命令后立即检索plpgsql中受影响的行数:
GET DIAGNOSTICS integer_var = ROW_COUNT;
Run Code Online (Sandbox Code Playgroud)
或者你可以OFFSET在PHP中使用.或其他客户端中的类似功能.
有关:
正如我在博客中描述的那样,MySQL有一个名为SQL_CALC_FOUND_ROWS的功能.这消除了两次执行查询的需要,但它仍然需要完整地进行查询,即使limit子句允许它提前停止.
据我所知,PostgreSQL没有类似的功能.在进行分页时要注意的一件事(使用LIMIT最常见的事情是恕我直言):执行"OFFSET 1000 LIMIT 10"意味着数据库必须至少获取1010行,即使它只给你10分.更高效的方法是记住前一行(在本例中为1000)排序的行的值,并重写查询,如下所示:"... WHERE order_row> value_of_1000_th LIMIT 10".优点是"order_row"很可能被索引(如果没有,你就会出问题).缺点是如果在页面视图之间添加新元素,这可能会有点不同步(但是再一次,它可能无法被访问者观察到并且可以获得很大的性能提升).
| 归档时间: |
|
| 查看次数: |
30419 次 |
| 最近记录: |