行级安全性(RLS)性能在postgres中明显较慢。

问题描述:

描述: 以下是性能问题的示例演示。行级安全性(RLS)性能在postgres中明显较慢。

我们首先创建了两个表,启用了行级安全性并创建了策略。

表定义:

create table sample_schema.sample_table1(ID numeric(38) PRIMARY KEY NOT NULL, 
       tenant_id VARCHAR(255) NOT NULL, 
       Description VARCHAR(255) 
     ); 

create table sample_schema.sample_table2(ID2 numeric(38) PRIMARY KEY NOT NULL, 
       tenant_id VARCHAR(255) NOT NULL, 
       table1_id numeric (38), 
       Description2 VARCHAR(255) 
     );  

创建索引:

CREATE UNIQUE INDEX sample_table1_idx1 ON sample_schema.sample_table1(tenant_id,id);    

启用行级别安全性:

ALTER TABLE sample_schema.sample_table1 ENABLE ROW LEVEL SECURITY; 

创建角色:

CREATE ROLE tenant_grp_role_p_id;  

创建策略:我希望有一个策略来选择数据,其中tenant_id列值有一定的作用是一样的谁已登录用户

CREATE POLICY Tenant_Roles ON sample_schema.sample_table1 TO tenant_grp_role_p_id USING ((tenant_id) IN (SELECT rolname FROM pg_roles WHERE pg_has_role(current_user, oid, 'member'))); 

创建示例数据:

insert into sample_schema.sample_table1 values (1,'user1_tenant1',1,'Table1 Data'); 
insert into sample_schema.sample_table2 values (2,'user1_tenant1',1,'Table2 Data'); 

问题:下面的查询不使用primary_key索引。

SELECT * FROM sample_schema.sample_table1 ST1, sample_schema.sample_table2 T2 WHERE ST1.id = ST2.table1_id AND ST1.id = 1;  

问题:如果启用RLS,当我禁用RLS然后主键索引使用。为什么是不使用主键索引扫描?

注意:
答:如果我禁用行级安全性并运行上述查询,它使用索引。
B.below是解释计划当低级安全被禁用时的输出。

Nested Loop (cost=0.29..19.19 rows=1 width=1129) -> Index Scan using sample_table1_pkey on sample_table1 st1 (cost=0.29..8.30 rows=1 width=37) 
    Index Cond: (id = '1'::numeric) -> Seq Scan on sample_table2 st2 (cost=0.00..10.88 rows=1 width=1092)  Filter: (table1_id = '1'::numeric);  

C.if我启用低级别安全性并运行查询它不使用索引。
及以下是解释计划启用低级别安全性时的输出。

Nested Loop (cost=1.03..946.65 rows=79 width=1129) -> Seq Scan on sample_table2 st2 (cost=0.00..10.88 rows=1 width=1092) Filter: (table1_id = '1'::numeric) -> Subquery Scan on st1 (cost=1.03..934.98 rows=79 width=37) 
    Filter: (st1.id = '1'::numeric)  -> Hash Join (cost=1.03..738.11 rows=15750 width=37)    Hash Cond: ((st1_1.tenant_id)::name = pg_authid.rolname)    -> Seq Scan on sample_table1 st1_1 (cost=0.00..578.00 rows=31500 width=37)    -> Hash (cost=1.01..1.01 rows=1 width=68)     -> Seq Scan on pg_authid (cost=0.00..1.01 rows=1 width=68)       Filter: pg_has_role("current_user"(), oid, 'member'::text); 

请帮我解决这个问题..

+1

请保留执行计划的格式和缩进。你将它们添加到你的问题的方式使它们无用。 –

+0

这与这个问题是一样的:http://stackoverflow.com/questions/41169479/postgresql-multi-tenant-mode-not-using-index#comment69569639_41169479 –

this message thread详细信息的pgsql-general邮件列表上。

我最近应用RLS几家大型(数百万行)在我的9.5数据库表 ,发现对一个大的RLS 保护表的查询执行良好,惟该加入几个大 RLS保护表的查询执行得不好。解释计划显示 优化程序正在扫描整个表,以在执行主键连接之前强制执行RLS策略 ,这会将查询结果从每个表中减少为单个行。如果在策略检查之前执行了加入,那么显然性能会更好,因为 会更好。

从我能理解的RLS实现努力执行 政策检查用户提供谓词检查,以避免 泄漏受保护的数据。

及其回应:

加入与RLS案件此刻不优化的非常好。有 正在努力改进 - 请参阅 https://www.postgresql.org/message-id/flat/8185.1477432701%40sss.pgh.pa.us - 但它不会在v10之前生产。

和:

您可以使用由同一用户 该表的下面是由国有独资的安全屏障观点,认为将绕过RLS的 表本身,因此你”您需要在安全屏障视图中实施适当的质量保证程序 。

因此,您可以等待PG10,或尝试使用security barrier view代替。该博客文章还解释了为什么Postgres没有试图结合(和优化)安全条件和用户指定的条件:可以使用自定义函数来泄漏否则将被用户隐藏的值。

要创建这样一个观点,只是添加with (security_barrier)的定义:

rhaas=# create or replace view unclassified_emp with (security_barrier) as 
     select * from emp where organization <> 'CIA'; 
CREATE VIEW 

有在this detailed blog post的更多信息了。