我在这里附加了一个查询,用于分析结果,https://explain.depesz.com/s/x9BN
这是查询
EXPLAIN ANALYZE
SELECT
branches.id as branch_id,
date(products.created_at + interval '1 hours 0 minutes') as date,
SUM(total_amount) as totalamount
FROM "products"
INNER JOIN "branches" ON "branches"."id" = "products"."branch_id"
WHERE (products.order_status_id NOT IN (10, 5, 50))
AND (products.company_id = 190)
AND (
products.created_at
BETWEEN '2019-01-30 23:00:00.000000'
AND '2019-12-30 23:00:00.000000'
)
GROUP BY branches.id, date;
我可以看到更多时间花在NOT IN()
的使用上。
我们还有其他功能可以用来提高性能。
答案 0 :(得分:3)
您的时间花费在访问许多包含您要搜索的行的表块上。也许许多块没有被缓存,并且存储也不快。
此查询可能永远不会比以前快,但您可以尝试以下两种方法:
使用多列索引:
#attributen button[class=color-changer],
#attributen input[id="reset"] {
width: 140px;
height: 35px;
}
如果这还不够快,请重写表,以使块按索引顺序物理排列:
CREATE INDEX ON products (company_id, creazed_at);
然后,将所需的行集中在较少的表块中,因此读取它们应该更快。
请注意,CLUSTER products USING idx_products_company_and_branch;
会阻止表在运行时对表的所有访问,并且由于表的修改会降低顺序,因此必须不时地对其进行重复。
答案 1 :(得分:2)
我怀疑not in
与常量是否直接导致您的性能问题。如果您发现问题,那是因为NOT IN
正在更改查询计划。
对于您而言,您拥有一些Postgres试图使用的部分有用的索引。我怀疑它提出了错误的查询计划,因为统计信息已过时。
对于此查询:
SELECT b.id as branch_id,
date(p.created_at + interval '1 hours 0 minutes') as date,
SUM(total_amount) as totalamount
FROM "products" p JOIN
"branches" b
ON b."id" = p."branch_id"
WHERE p.order_status_id NOT IN (10, 5, 50) AND
p.company_id = 190 AND
p.created_at >= '2019-01-30 23:00:00.000000' AND
p.created_at < '2019-12-30 23:00:00.000000'
GROUP BY b.id, date;
请注意,我调整了日期比较,因为between
包括两个端点。
我建议以下索引:
products(company_id, created_at, order_status_id)
branches(id)
。