#3041·crystal

V5: 使用 RLS 时性能下降

作者: maximsmol创建于 2026年5月1日更新于 2026年8月28日

前者查询速度慢得多,如果public.table很大,RLS 会参与其中,因为规划器为将通过过滤器的行数创建了一个非常糟糕的估计计划。该计划通常如下所示:

sql
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