【发布时间】:2020-08-24 11:56:51
【问题描述】:
我有一个多租户环境,其中每个租户(客户)都有自己的架构来隔离他们的数据。我知道这并不理想,但它是旧系统的快速移植。
每个租户都有一个“阅读”表,具有 4 列的复合索引: site_code char(8)、location_no int、sensor_no int、reading_dtm timestamptz。
当添加新读数时,会调用一个函数,该函数首先检查是否在最后一分钟已经有读数(对于相同的 site_code.location_no.sensor_no):
IF EXISTS (
SELECT
FROM reading r
WHERE r.site_code = p_site_code
AND r.location_no = p_location_no
AND r.sensor_no = p_sensor_no
AND r.reading_dtm > p_reading_dtm - INTERVAL '1 minute'
)
THEN
RETURN;
END IF;
现在,请记住,有许多租户,除了 1 之外,所有租户都表现良好。在其中 1 个租户中,调用花费了近半秒而不是通常的几毫秒,因为它正在对一张表进行顺序扫描近 200 万行而不是索引扫描。
我的 random_page_cost 设置为 1.5。
如果查询可能返回很多行,我可以理解顺序扫描,检查是否存在。
我已经在桌子上尝试过 ANALYZE、VACUUM FULL 等,但没有任何区别。
如果我在查询前加上“SET LOCAL enable_seqscan = off”,它工作得很好......但感觉不对,但它必须是一个临时解决方案,因为这是一个实时系统,它需要工作。
我还能做些什么来帮助 Postgres 做出使用索引的更好决定?
编辑:如果我手动(在函数之外)执行类似的查询,它会选择一个索引。
【问题讨论】:
-
由于某种原因,PostgreSQL 认为谓词
r.reading_dtm > p_reading_dtm - INTERVAL '1 minute'的选择性不够。 -
我想知道这是否与函数内部缓存的执行计划有关
-
可能是 - 如果我手动模仿查询,它会选择索引扫描。
标签: postgresql