V5: 使用 RLS 时性能下降
作者: maximsmol创建于 2026年5月1日更新于 2026年8月28日
前者查询速度慢得多,如果public.table很大,RLS 会参与其中,因为规划器为将通过过滤器的行数创建了一个非常糟糕的估计计划。该计划通常如下所示:
Hash Join (cost=... rows=75 width=...) (actual time=... rows=0 loops=1)
Hash Cond: (__table__.id = ((ids.value ->> 0))::bigint)
-> Seq Scan on table __table__ (cost=... rows=1000000 width=...) (actual time=... rows=0 loops=1)
Filter: (table_rls(...))
Rows Removed by Filter: 1500000
-> Hash (cost=1.00..1.00 rows=100 width=40) (never executed)
-> Function Scan on json_array_elements ids (cost=0.00..1.00 rows=100 width=40) (never executed)
注意,`Seq Scan` 的估计非常糟糕。它假定大部分表是可见的,但 RLS 实际上会将其丢弃。
这可能会被对 `ids` 的卡方估计的差异加剧,因为上述计划是使用 `ids := [null]` 创建的。`json_array_elements` 的卡方总是估计为 `100`,无论输入如何
在 V4 中,计划要好得多。我只是猜测,但这可能是因为规划器直接基于 ID 进行连接,因此连接的卡方不受 `json_array_elements` 函数的影响。以下是计划的大纲:
```sql
SubPlan 1
-> Index Scan using table_pkey …内容来源: graphile/crystal