1

描述: 以下是性能問題的示例演示。行級安全性(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 –

回答

2

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的更多信息了。