5

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

在这个例子中,我有 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 行,25K 产品在超过 8800 毫秒内执行,这对我来说是不可接受的。

所有伪造的密钥都有索引,最近对 DB 进行了真空分析。

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

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

我还能做些什么来加快这个查询?

解释分析:
- 订购缓慢: http: //explain.depesz.com/s/AHO
- 快速无订购:http ://explain.depesz.com/s/NRxr

4

1 回答 1

1

一种可能的方法是stores从联接中删除。相反,您可以:

  • 在存储过程或源代码中循环遍历stores(order by ),并且对于每个存储,在 上执行连接过滤。只要获得足够数量的记录,就可以中断循环。s_namestocks.fk_store

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

这样,你应该有一个很好的好处。

于 2012-11-07T14:24:10.043 回答