使用Count优化分页和筛选查询结果

时间:2012-08-15 18:44:26

标签: php postgresql heroku pagination filtering

我在处理许多电子商务网站上的分页和过滤产品时遇到了性能问题,这里是Zappos的一个例子

标准的种类:
显示132项结果中的1-10项。 [上一页] 1 2 [3] 4 ... 13 [下一页]
[10]每页结果

对我而言,似乎问题的很大一部分是查询运行两次,一次计算结果数量并再次实际填充数组。以下是“过滤器”查询:

SELECT product_id, product_title, orderable
FROM table_view
WHERE (family_title = 'Shirts' OR category_title = 'Shirts')
AND ((detail_value = 'Blue' AND detail_title = 'Color')
OR (detail_value = 'XL' AND detail_title = 'Size'))
GROUP BY product_id, product_title, orderable
HAVING COUNT(detail_title)=2
ORDER BY product_id
LIMIT 10 OFFSET 0

查询大约需要20毫秒才能自行运行。它从中选择的表是一个视图,它是大约五个不同表的连接。用户传入的参数是“detail_value”& “detail_title”是过滤标准。 “家庭”和“类别”然后限制由“每页结果”设置。因此,如果他们想查看所有结果,则限制设置为2000.每次他们通过分页进入新页面时,将再次运行整个查询。下面是PHP的一个片段,$ products是查询结果的数组。然后$ number_of_results是具有最大限制的相同事物的计数。

$products = filter($value, $category_title, $number_per_page, $subcategory, $start_number);

$number_of_results = count(filter($value, $category_title, 2000, $subcategory, 0));

$pages = ceil($number_of_results / $number_per_page);

在本地计算机上运行时,结果页面需要大约600-800ms才能加载,当部署到Heroku时,页面需要13-16秒才能加载。我遗漏了很多PHP代码,但是我使用PHP的PDO类将查询结果变成一个在PHP中显示的对象。要连接的表是产品表,类别表,详细信息表以及通过外键链接它们的两个表。

谷歌的结果表明,这是一个非常常见/复杂的问题,但我还没有找到适合我的任何真正的解决方案。

1 个答案:

答案 0 :(得分:0)

分页的许多查询通常需要运行几次:一次确定将显示多少条记录,然后再次抓取一个记录屏幕。然后后续查询抓住下一个记录屏幕等等。

缓慢分页查询的两个解决方案是:

  1. 使用游标从打开的查询结果集中提取n记录
  2. 加快查询速度
  3. 对于服务器的资源,解决方案1的内存可能很昂贵,如果有许多并发用户生成这样的查询,则可能无法很好地扩展。使用您正在使用的PDO类实现游标可能也很困难。

    解决方案2可以通过改进视图查询,添加索引等来完成。但这可能还不够。如果表的读取频率比写入的频率高得多,您可以尝试使用UPDATE / INSERT / DELETE触发器技巧。不是针对VIEW运行查询,而是创建一个具有与VIEW相同的列结构和数据的表。每当其中一个基础表发生更改时,请手动修改此新表以跟踪更改。这会减慢写入速度,但会大大提高读数。

相关问题