使用多个 IN 优化查询

Optimizing a query with multiple IN

我有这样的查询:

SELECT * FROM table
WHERE department='param1' AND type='param2' AND product='param3'
AND product_code IN (10-30 alphanumerics) AND unit_code IN (10+ numerics)
AND first_name || last_name IN (10-20 names)
AND sale_id LIKE ANY(list of regex string)

运行时间太长,所以我被要求优化它。

参数列表因不同用户的代码列而异。 每个用户提供他们的代码列表,然后循环访问产品。 product 曾经也是一个 IN 子句列表,但它被拆分了。

我尝试过的东西

通过在(部门、类型和产品)上添加索引,我获得了 4 倍的改进。 目前的运行时间是product有的值只需要2-3秒,有的需要30s。

尝试创建 first_name 的预连接列 || last_name,但运行时改进太小,不值得。

有什么方法可以提高其他子句的性能,例如“IN”子句或 LIKE ANY 子句?

根据我的经验,使用 VALUES 子句的 JOIN 替换大型 IN 列表通常会提高性能。

所以代替:

SELECT * 
FROM table
WHERE department='param1' 
  AND type='param2' 
  AND product='param3'
  AND product_code IN (10-30 alphanumerics)

使用:

SELECT * 
FROM table t
   JOIN ( values (1),(2),(3) ) as x(code) on x.code = t.product_code
WHERE department='param1' 
  AND type='param2' 
  AND product='param3'

但是您必须确保 values () 列表中没有任何重复项


连接也是错误的,因为连接后的值与单独比较每个值不同,例如('alexander', 'son') would be treated identical to ('alex', 'anderson')`

你应该使用:

and (first_name, last_name) in ( ('fname1', 'lname1'), ('fname2', 'lname2'))

这个也可以写成join

SELECT * 
FROM table t
  JOIN ( values (1),(2),(3) ) as x(code) on x.code = t.product_code
  JOIN ( 
     values ('fname1', 'lname1'), ('fname2', 'lname2') 
  ) as n(fname, lname) on (n.fname, n.lname) = (t.first_name, t.last_name)
WHERE department='param1' 
  AND type='param2' 
  AND product='param3'

您通常不需要做任何特殊的事情来使索引能够与多个 IN 列表一起使用,除了保持 table 良好的清理和分析。 (department, type, product, product_code, unit_code, (first_name || last_name)) 上的 btree 索引应该运行良好。如果没有,请为其显示 EXPLAIN (ANALYZE, BUFFERS),最好打开 track_io_timing。如果您的每个条件的选择性不是相互独立的,那可能会导致规划问题。