我有一个问题:我有两个行安全策略来限制对一个表的访问。第一个策略使用数组列“权限”。“right”列类型为16位位/整数数组,并为每个用户分配一个索引。如果数组在索引处的值为1,则具有该索引的用户可以读取该行。如下所示的政策:
CREATE POLICY policy_testdata_select ON testdata
FOR SELECT TO PUBLIC
USING (rights[(select array_pos from account where username = current_user)] > 0);第二个策略使用具有相同逻辑的位字符串,例如:
表中值: 1001010
User1位字符串: 0001000
User2位字符串: 0000100
1001010 & 0001000 = 0001000 -> User1有访问权限
1001010 & 0000100 = 0000000 -> User2没有访问权限
该政策如下:
CREATE POLICY policy_testdata_select ON testdata
FOR SELECT TO PUBLIC
USING ((bitstring & (select user_bitstring from account where username = current_user)) <> B'0'::BIT(16));从直觉上讲,我认为第二个选项具有更高的性能,因为位字符串不会消耗大量内存,二进制操作也不会花费很多,但是如果比较性能,数组版本甚至会更快一些。怎么会这样?以下是两个具有相同测试数据的评估计划(200万行,用户可以访问一半):
Array:
QUERY PLAN
---------------------------------------------------------------------------------------------------------------------------------------------
Limit (cost=10000000008.16..10000526114.16 rows=666667 width=1160) (actual time=0.025..2733.524 rows=1000000 loops=1)
InitPlan 1 (returns $0)
-> Index Scan using username2_index on account2 (cost=0.14..8.16 rows=1 width=4) (actual time=0.014..0.014 rows=1 loops=1)
Index Cond: (username = CURRENT_USER)
-> Seq Scan on testdata (cost=10000000000.00..10000526106.00 rows=666667 width=1160) (actual time=0.025..2660.927 rows=1000000 loops=1)
Filter: (rights[$0] > 0)
Rows Removed by Filter: 1000000
Planning Time: 0.181 ms
Execution Time: 2768.561 ms
(9 rows)
Bitstring:
QUERY PLAN
----------------------------------------------------------------------------------------------------------------------------------------------
Limit (cost=10000000008.16..10000266895.60 rows=1000000 width=1160) (actual time=0.026..2759.098 rows=1000000 loops=1)
InitPlan 1 (returns $0)
-> Index Scan using username2_index on account2 (cost=0.14..8.16 rows=1 width=7) (actual time=0.013..0.014 rows=1 loops=1)
Index Cond: (username = CURRENT_USER)
-> Seq Scan on testdata (cost=10000000000.00..10000531106.00 rows=1990000 width=1160) (actual time=0.025..2685.145 rows=1000000 loops=1)
Filter: ((bitstring & $0) <> '0000000000000000'::bit(16))
Rows Removed by Filter: 1000000
Planning Time: 0.167 ms
Execution Time: 2794.719 ms
(9 rows)两个版本之间的一些比较(黄色和紫色-蓝色,没有任何策略) x-Axis:千行计数,y-Axis:查询的平均执行时间:

还有另一个问题:是否有更好的方法来过滤访问。对一条线的权利是可以改变的。例如,是否有可能建立一个加速过滤过程的索引?
发布于 2019-09-06 12:36:43
数据结构有多大并不重要,只要行足够小,不能使TOASTed (存储在行外,在这种情况下,访问变得更昂贵)。
您所测量的性能差异可能是不同操作符的成本(&与数组元素访问)。
我不相信你能比你做得更有效率。行级安全性带来的性能命中与检查的行数有理想的比例,而且性能影响将在像顺序扫描这样的廉价访问路径中最明显。
https://dba.stackexchange.com/questions/247150
复制相似问题