小编Mad*_*ist的帖子

互斥的多对多关系

我有一个containers可以与多个表建立多对多关系的表,假设它们是plantsanimalsbacteria。每个容器可以包含任意数量的植物、动物或细菌,并且每个植物、动物或细菌可以在任意数量的容器中。

到目前为止,这非常简单,但我遇到的问题是每个容器应该只包含相同类型的元素。例如,同时包含植物和动物的混合容器应该是数据库中的约束违规。

我的原始架构如下:

containers
----------
id
...
...


containers_plants
-----------------
container_id
plant_id


containers_animals
------------------
container_id
animal_id


containers_bacteria
-------------------
container_id
bacterium_id
Run Code Online (Sandbox Code Playgroud)

但是对于这个模式,我无法想出如何实现容器应该是同构的约束。

有没有办法通过参照完整性来实现这一点,并在数据库级别确保容器是同类的?

我为此使用 Postgres 9.6。

postgresql database-design constraint many-to-many

9
推荐指数
2
解决办法
1891
查看次数

带有 btree 索引的 jsonb 列的统计数据不一致

我注意到涉及 jsonb 列的查询的性能在测试时在 VACUUM ANALYZE 运行之间存在显着差异。分析表格后,我似乎随机得到了完全不同的执行计划。

我在这里使用 Postgres 9.6。我的测试设置如下,我将一个键“x”插入到 jsonb 列“params”中,值在 1 到 6 之间,1 是最稀有的值,6 是最常见的值。我还有一个常规的 int 列“single_param”,其中包含用于比较的相同值分布。:

CREATE TABLE test_data (
    id      serial,
    single_param    int,
    params      jsonb
);

INSERT INTO test_data
SELECT 
    generate_series(1, 1000000) AS id, 
    floor(log(random() * 9999999 + 1)) AS single_param,
    json_build_object(
        'x', floor(log(random() * 9999999 + 1))
    ) AS params;

CREATE INDEX idx_test_btree ON test_data (cast(test_data.params->>'x' AS int));
CREATE INDEX idx_test_gin ON test_data USING GIN (params);
CREATE INDEX ON test_data(id)
CREATE INDEX ON test_data(single_param)
Run Code Online (Sandbox Code Playgroud)

我正在测试的查询是对结果进行分页的典型查询,我按 …

postgresql statistics execution-plan index-tuning json

7
推荐指数
1
解决办法
1739
查看次数

具有单个数据库用户和连接池的行级安全性

我正在使用node-postgres连接到启用了连接池的 PostgreSQL 9.6 数据库。所有连接都使用同一个数据库用户。我不能使用多个数据库用户的一个原因是,据我所知,在这种情况下,行级安全性和视图不能很好地协同工作,因为视图的所有者用于 RLS。

我现在正在考虑在 Postgres 中使用行级安全性,我想确保我这样做是正确的。

我正在使用SET LOCAL设置当前应用程序用户 ID,然后由行级安全性 USING 子句使用。我能想到通过连接池实现这一点的唯一方法是使用 node-postgres 将每个查询包装在一个事务中,并SET LOCAL在每个事务中执行如下命令。

SET LOCAL postgres.my_user = 20;
Run Code Online (Sandbox Code Playgroud)

以下代码是我想如何定义行级安全性的简化示例,真实版本还有一些条件:

CREATE POLICY table_a_read_policy ON table_a FOR SELECT
USING (
    EXISTS (
    SELECT * 
    FROM permissions 
    WHERE 
        user_id = current_setting('postgres.my_user')::int AND 
        permission_type = 'read'
    )
);
Run Code Online (Sandbox Code Playgroud)

我的理解是,在这种情况下,任何 SQL 注入也会使攻击者能够以这种方式设置任何用户 ID 并规避行级安全性。但是我没有看到任何方法可以避免这种情况,因为我连接的数据库用户必须能够查看整个应用程序的所有数据。

有几点我不完全确定:

  • 使用SET LOCAL作为存储当前应用程序用户身份以实现行级安全的方式是否安全?尤其是在连接池的上下文中?
  • 有没有比在 node-postgres 中的事务中包装每个查询并SET LOCAL每次执行命令更好的方法?
  • 有没有办法以一种 SQL 注入不会自动提供规避行级安全性的能力的方式来构造它(限制使用单个数据库用户建立数据库连接)?

postgresql row-level-security

5
推荐指数
1
解决办法
2493
查看次数

即使存在正确的索引,聚合列也会导致全表扫描

我有一个查询,我想从 date_ added 列排序的表数据集中获取前几行。排序依据的列被索引,所以这个表的基本版本非常快:

SELECT datasets.id FROM datasets ORDER BY date_added LIMIT 25
Run Code Online (Sandbox Code Playgroud)

"Limit  (cost=0.28..6.48 rows=25 width=12) (actual time=0.040..0.092 rows=25 loops=1)"
"  ->  Index Scan using datasets_date_added_idx2 on datasets  (cost=0.28..1244.19 rows=5016 width=12) (actual time=0.037..0.086 rows=25 loops=1)"
"Planning time: 0.484 ms"
"Execution time: 0.139 ms"
Run Code Online (Sandbox Code Playgroud)

但是一旦我使查询变得更复杂,我就会遇到问题。我想加入另一个表示多对多关系的表,并将结果聚合在一个数组列中。为此,我需要添加一个 GROUP BY id 子句:

SELECT datasets.id FROM datasets GROUP BY datasets.id ORDER BY date_added LIMIT 25
Run Code Online (Sandbox Code Playgroud)

"Limit  (cost=551.41..551.47 rows=25 width=12) (actual time=9.926..9.931 rows=25 loops=1)"
"  ->  Sort  (cost=551.41..563.95 rows=5016 width=12) (actual time=9.924..9.926 rows=25 loops=1)"
" …
Run Code Online (Sandbox Code Playgroud)

postgresql performance optimization postgresql-9.5 query-performance

4
推荐指数
1
解决办法
1046
查看次数