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, то индекс первичного ключа используется .why это не с помощью первичного ключа индексного сканирования, когда RLS включен?

Примечание:
A. Если я отключу безопасность на уровне строк и запустив вышеуказанный запрос, он использует индекс.
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-списке рассылки для деталей.

Я недавно подал RLS нескольких крупных (нескольких миллионов строк) таблицы в моей базе данных 9.5 и заметил, что запросы к один большому RLS защищаемой таблицы работают хорошо, однако запросы, которые объединяют несколько крупных RLS защищенных таблиц выполняют очень плохо. В плане объяснения показано, что оптимизатор сканирует всю таблицу, чтобы обеспечить соблюдение политики RLS перед выполнением объединения первичного ключа, что уменьшит результаты запроса до одной строки из каждой таблицы. Очевидно, что производительность будет лучше, если она выполнит соединение до проверки политики.

Из того, что я могу понять, реализация RLS стремится выполнить проверки политики до того, как пользователь предоставил проверки предикатов, чтобы избежать утечки защищенных данных.

И ответы:

Регистрация случаи с RLS не оптимизированы очень хорошо на данный момент. Для этого необходимо выполнить , см. https://www.postgresql.org/message-id/flat/8185.1477432701%40sss.pgh.pa.us - но он не будет представлен на производстве до версии 10.

И:

Вы можете использовать вид барьера безопасности, который принадлежит тому же пользователю , что таблицы под принадлежат, что обойдет 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 тоже.

Смежные вопросы