英文:
PostgreSQL Row-Level Security is NOT Using Table Indexes
问题
I have the following table with a million rows of data.
SELECT COUNT(*) FROM people; -- 1,000,000 rows
I have created the following 2 indexes:
Without the RLS enabled, I checked the explain plan of the following query and you can see that it is using the index that I have created for the ct_data JSONB column.
I enabled Row Level Security by issuing the following commands. The table policy is just a simple condition to have select access on the table.
With the RLS enabled, I rechecked the explain plan of the same query but this time, it did not use the index and it is doing a parallel sequential scan instead on the "people" table.
Why is RLS not using the indexes? Appreciate if you could provide some guidance to still implement RLS but not sacrifice performance.
At the moment, if I try to do an update on the ct_data column of the "people" table, it is taking so much time to complete the update especially after I add another simple table policy for the UPDATE DML operation like:
英文:
I have the following table with a million rows of data.
SELECT COUNT(*) FROM people; -- 1,000,000 rows
I have created the following 2 indexes:
Without the RLS enabled, I checked the explain plan of the following query and you can see that it is using the index that I have created for the ct_data JSONB column.
I enabled Row Level Security by issuing the following commands. The table policy is just a simple condition to have select access on the table.
With the RLS enabled, I rechecked the explain plan of the same query but this time, it did not use the index and it is doing a parallel sequential scan instead on the "people" table.
Why is RLS not using the indexes? Appreciate if you could provide some guidance to still implement RLS but not sacrifice performance.
At the moment, if I try to do an update on the ct_data column of the "people" table, it is taking so much time to complete the update especially after I add another simple table policy for the UPDATE DML operation like:
答案1
得分: 3
操作符->
不是防泄漏的:
SELECT oprcode
FROM pg_operator
WHERE oprname = '->'
AND oprleft = 'jsonb'::regtype
AND oprright = 'text'::regtype;
oprcode
════════════════════
jsonb_object_field
(1 行)
SELECT proleakproof
FROM pg_proc
WHERE proname = 'json_object_field';
proleakproof
══════════════
f
(1 行)
不是防泄漏的函数和操作符不会在 RLS 策略的条件之前进行优化,出于安全原因。
解决方案是将id
列从jsonb
中提取出来,并将其定义为常规数值列。数值数据类型的=
操作符是防泄漏的。
英文:
The problem is that the operator ->
is not leakproof:
SELECT oprcode
FROM pg_operator
WHERE oprname = '->'
AND oprleft = 'jsonb'::regtype
AND oprright = 'text'::regtype;
oprcode
════════════════════
jsonb_object_field
(1 row)
SELECT proleakproof
FROM pg_proc
WHERE proname = 'json_object_field';
proleakproof
══════════════
f
(1 row)
Functions and operators that are not leakproof are not optimized to be applied before the condition from the RLS policy for security reasons.
The solution is to pull that id
column out of the jsonb
and define it a a regular numeric column. The =
operators for numeric data types are leakproof.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论