首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Posgres行安全策略-为什么数组比Bitstring快?

Posgres行安全策略-为什么数组比Bitstring快?
EN

Database Administration用户
提问于 2019-09-06 10:50:10
回答 1查看 54关注 0票数 1

我有一个问题:我有两个行安全策略来限制对一个表的访问。第一个策略使用数组列“权限”。“right”列类型为16位位/整数数组,并为每个用户分配一个索引。如果数组在索引处的值为1,则具有该索引的用户可以读取该行。如下所示的政策:

代码语言:javascript
复制
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没有访问权限

该政策如下:

代码语言:javascript
复制
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万行,用户可以访问一半):

代码语言:javascript
复制
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:查询的平均执行时间:

还有另一个问题:是否有更好的方法来过滤访问。对一条线的权利是可以改变的。例如,是否有可能建立一个加速过滤过程的索引?

EN

回答 1

Database Administration用户

发布于 2019-09-06 12:36:43

数据结构有多大并不重要,只要行足够小,不能使TOASTed (存储在行外,在这种情况下,访问变得更昂贵)。

您所测量的性能差异可能是不同操作符的成本(&与数组元素访问)。

我不相信你能比你做得更有效率。行级安全性带来的性能命中与检查的行数有理想的比例,而且性能影响将在像顺序扫描这样的廉价访问路径中最明显。

票数 1
EN
页面原文内容由Database Administration提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://dba.stackexchange.com/questions/247150

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档