使用多个连接,按顺序和小限制优化PostgreSQL查询

时间:2012-11-07 13:33:31

标签: sql postgresql query-optimization

我需要一些优化从大表中获取查询的技巧。

在这个例子中我有5个表:

Brands
- id_brand
- b_name

Products
- id_product
- p_name
- ean
...
- fk_brand

Prod_attributes
- id_prod_att
- size_basic
...
- fk_product

Stores
- id_store
- s_name
...

Stocks
- id_stock
- stock_amount
- fk_prod_att
- fk_store

我需要查询有序的股票有序列表,所以这是我使用的一般方法:

SELECT stores.s_name, stocks.stock_amount, prod_attributes.size_basic, 
products.p_name, products.ean, brands.b_name 

FROM (stocks 
    INNER JOIN stores 
    ON stocks.fk_store = stores.id_store) 
    INNER JOIN (prod_attributes 
        INNER JOIN (products 
            INNER JOIN brands 
            ON products.fk_brand = brands.id_brand) 
        ON prod_attributes.fk_product = products.id_product) 
    ON stocks.fk_prod_att = prod_attributes.id_prod_att 

ORDER BY s_name, p_name, size_basic 

LIMIT 25 OFFSET 0

这适用于小型表,但是当表增长时,查询变得非常昂贵。 Stocks中有3,5M行,Prod_attributes中有300K,超过8800ms时执行25K产品,这对我来说是不可接受的。

所有forgein键都有索引,DB最近已经过真空分析。

我知道问题出在ORDER BY部分,因为查询不使用索引并进行顺序扫描。如果我删除了排序,那么查询速度非常快。

为了解决这个问题,我知道我可以删除ORDER BY,但对我来说这不是一个可行的选择。数据库或物化视图的反规范化也可以在这里提供帮助 - 如果可能的话,我想再次避免这种情况。

我还能做些什么来加快查询速度?

EXPLAIN ANALYZE:
- 订单减慢:http://explain.depesz.com/s/AHO
- 快速无订单:http://explain.depesz.com/s/NRxr

1 个答案:

答案 0 :(得分:1)

可行的方法是从联接中删除stores。相反,你可以:

  • 在存储过程或源代码中循环stores(按s_name排序),对于每个商店,在stocks.fk_store上执行联接过滤。只要获得足够数量的记录,就可以打破循环。

  • 如果可能,请使用stocks键对fk_store进行分区,以便大量减少连接中元组的数量。

通过这种方式你应该有一个很好的好处。