Nus*_*evi 5 sql postgresql row-level-security database-indexes postgresql-performance
描述:这是性能问题的示例演示。
我们首先创建了两个表,启用了行级安全性,还创建了策略。
表定义:
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)
);
Run Code Online (Sandbox Code Playgroud)
索引创建:
CREATE UNIQUE INDEX sample_table1_idx1 ON sample_schema.sample_table1(tenant_id,id);
Run Code Online (Sandbox Code Playgroud)
启用行级安全性:
ALTER TABLE sample_schema.sample_table1 ENABLE ROW LEVEL SECURITY;
Run Code Online (Sandbox Code Playgroud)
创建角色:
CREATE ROLE tenant_grp_role_p_id;
Run Code Online (Sandbox Code Playgroud)
创建策略:我希望策略选择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')));
Run Code Online (Sandbox Code Playgroud)
创建样本数据:
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');
Run Code Online (Sandbox Code Playgroud)
问题:以下查询未使用primary_key index。
SELECT * FROM sample_schema.sample_table1 ST1, sample_schema.sample_table2 T2 WHERE ST1.id = ST2.table1_id AND ST1.id = 1;
Run Code Online (Sandbox Code Playgroud)
问题:如果禁用RLS,则使用主键索引。为什么启用RLS时不使用主键索引扫描?
注意:
答:如果禁用行级安全性并运行上述查询,它将使用索引。
B.以下是说明计划禁用低级别安全性时的输出。
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);
Run Code Online (Sandbox Code Playgroud)
C.如果启用低级安全性并运行查询,则不使用索引。
下面是启用低级安全性时的说明计划输出。
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);
Run Code Online (Sandbox Code Playgroud)
请帮助我解决此问题..
有关详细信息,请参见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,或者尝试使用安全屏障视图。那篇博客文章还解释了为什么Postgres不尝试结合(优化)安全性条件和用户指定的条件:自定义函数可以用于泄漏本来对用户隐藏的值。
要创建这样的视图,只需添加with (security_barrier)
到定义中:
rhaas=# create or replace view unclassified_emp with (security_barrier) as
select * from emp where organization <> 'CIA';
CREATE VIEW
Run Code Online (Sandbox Code Playgroud)
在这个详细的博客文章中也有更多信息。
归档时间: |
|
查看次数: |
3828 次 |
最近记录: |