我是postgresql的新手,但我对mysql有很好的体验。我正在阅读文档,我发现postgresql有一个数组类型。我很困惑,因为我无法理解这种类型在rdbms中有用。为什么我必须选择这种类型而不是使用经典的一对多关系?
提前致谢。
答案 0 :(得分:4)
我已经使用它们来更容易地使用树(例如注释线程)。您可以将树的根路径存储到数组中的单个节点,数组中的每个数字都是该节点的分支编号。然后,你可以这样做:
SELECT id, content
FROM nodes
WHERE tree = X
ORDER BY path -- The array is here.
PostgreSQL将以自然的方式逐元素地比较数组,因此ORDER BY path
将以合理的线性显示顺序转储树;然后,检查path
的长度以确定节点的深度,并给出缩进以使渲染正确。
上述方法可以让您从数据库到渲染页面,只需一次通过数据。
PostgreSQL也有geometric types,简单key/value types,并支持构建其他各种composite types。
通常最好使用传统的关联表,但在工具箱中使用更多工具并没有错。
答案 1 :(得分:1)
一位SO用户正在将其用于看似machine-aided translation的内容。对follow-up question的评论可能有助于理解他的方法。
答案 2 :(得分:1)
我一直在成功使用它们来使用触发器聚合递归树引用。
例如,假设您有一个类别树,并且您想要查找任何类别(1,2,3)或其任何子类别中的产品。
一种方法是使用丑陋的with recursive
语句。这样做会输出一个计划,其中包含整个表上的合并/散列连接以及偶尔的实现。
with recursive categories as (
select id
from categories
where id in (1,2,3)
union all
...
)
select products.*
from products
join product2category on...
join categories on ...
group by products.id, ...
order by ... limit 10;
另一种方法是预先汇总所需的数据:
categories (
id int,
parents int[] -- (array_agg(parent_id) from parents) || id
)
products (
id int,
categories int[] -- array_agg(category_id) from product2category
)
index on categories using gin (parents)
index on products using gin (categories)
select products.*
from products
where categories && array(
select id from categories where parents && array[1,2,3]
)
order by ... limit 10;
上述方法的一个问题是&&和运营商是垃圾。 (选择性是一个尚未编写的存根函数,无论聚合中的值如何,都会产生大约1/200行。)换句话说,你很可能最终得到一个seq扫描的索引扫描这是正确的。
为了解决这个问题,我增加了gin-indexed列的统计数据,并定期查看pg_stats以提取更合适的统计数据。粗略地看一下这些统计数据就会发现使用&&对于指定的值将返回一个不正确的计划,我重写适当的&&&使用arrayoverlap()(后者的存根选择性为1/3),例如:
select products.*
from products
where arrayoverlap(cat_id, array(
select id from categories where arrayoverlap(parents, array[1,2,3])
))
order by ... limit 10;
(同样适用于< @运算符......)