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

时间:2016-12-16 14:47:11

标签: sql postgresql postgresql-performance database-indexes row-level-security

描述: 以下是性能问题的示例演示。

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

表格定义:

filename = input('give me a filename: ', 's');

索引创建:

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;   

创建策略:我希望策略选择其中tenant_id列值的角色与已登录用户相同的数据。

CREATE ROLE tenant_grp_role_p_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')));

问题:以下查询未使用primary_key索引。

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');

问题:如果我禁用RLS,则使用主键索引。为什么在启用RLS时不使用主键索引扫描?

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

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

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

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);    

请帮我解决这个问题..

1 个答案:

答案 0 :(得分:5)

有关详细信息,请参阅pgsql-general邮件列表中的this message thread

  

我最近将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不会尝试组合(和优化)安全条件和用户指定的条件:自定义函数可用于泄漏否则将被用户隐藏的值。

要创建此类视图,只需将 lat += 0.5 * pi; => 0x0000000000f34ca3 <+327>: mov -0x20(%rbp),%rax 0x0000000000f34ca7 <+331>: movsd (%rax),%xmm1 0x0000000000f34cab <+335>: movsd 0xcfee57d(%rip),%xmm2 # 0xdf23230 <_ZN3abc2piE> 0x0000000000f34cb3 <+343>: movsd 0x127735(%rip),%xmm0 # 0x105c3f0 0x0000000000f34cbb <+351>: mulsd %xmm2,%xmm0 0x0000000000f34cbf <+355>: addsd %xmm1,%xmm0 0x0000000000f34cc3 <+359>: mov -0x20(%rbp),%rax 0x0000000000f34cc7 <+363>: movsd %xmm0,(%rax) 添加到定义:

with (security_barrier)

this detailed blog post中还有更多信息。