如何避免在分页中运行两次相同的昂贵的MySql查询?

时间:2013-05-03 09:08:48

标签: mysql sql coldfusion

假设houses表包含许多字段,相关图像表和其他3个相关表。我有一个昂贵的查询,它检索所有houses数据,包含相关表中的所有数据。在分页的情况下,我是否需要运行相同的昂贵的MySql查询两次:一次用于当前结果页面,一次用于获取记录总数?

我正在使用Limit 0,10的服务器端分页,并且需要返回房屋总数以及数据。使用count(*)函数运行相同的昂贵查询对我来说没有意义,因为我限制了分页的结果集。 是否有另一种方法可以指示MySQL计算整个查询,但只返回当前的分页数据?

我希望我的问题很明确...... 谢谢

2 个答案:

答案 0 :(得分:1)

我不知道MySql但是对于很多dbs,我认为你会发现运行它两次的成本没有你想象的那么高 - 如果你这样做就是db的优化引擎认为这两个查询有很多共同之处。

运行

select count(1) from (
  select some_fields, row_number over (order by field) as rownum
  from some_table
)

然后

select * from (
  select some_fields, row_number over (order by field) as rownum
  from some_table
)
where rownum between :startRow and :endRow
order by row_number

这样做的另一个好处是,您可以在一个地方维护查询,周围有两个不同的包装器,1个用于分页,1个用于获取总计数。

正如旁注,您可以做的最佳优化是确保每次都向db发送完全相同的查询。换句话说,如果用户可以更改排序或更改他们可以查询的字段,请将其全部烘焙到同一查询中。 E.g:

select some_fields,
   case 
     when :sortField = 'ID' and :sortType = 'asc' 
       then row_number over (order by id)
     when :sortField = 'ID' and :sortType = 'desc' 
       then row_number over (order by id desc)
   end as rownum
from some_table
where (:searchType = 'name' 
  and last_name like :lastName and first_name like :firstName)
or  (:searchType = 'customerType' 
  and customer_type = :customer_type)

答案 1 :(得分:0)

cfquery有一个可能有用的记录计数变量。您还可以使用cfoutput的startrow和maxrows属性来控制显示的记录数。最后,您可以将查询结果缓存在coldfusion中,这样您就不必每次都对数据库运行它。