SP-GiST运算符家族“ text_ops”使用特里索引。因为UUID很长而且非常不同,所以即使我只进行完全匹配搜索,这些听起来也很吸引人。
还有一个哈希选项。哈希是O(1),当然除了相等以外,我不需要进行任何比较,但是由于UUID很长,因此恐怕从它们生成哈希值会浪费很多时间。
或者这是否过于依赖系统和使用细节?
在大多数情况下,我宁愿使用bigserial,但是有人告诉我为此使用uuid。我们需要uuid,因为我们可能有多个使用不同数据库的服务器,因此不能保证我们将拥有唯一的bigint。我们可以为每个服务器使用不同的序列(和种子),但是它仍然不如UUID灵活。例如,如果不将ID及其引用转换到各处,就无法将数据库条目从一台服务器迁移到另一台服务器。
#1 楼
使用PostgreSQL内置的uuid
数据类型,并在其上创建常规b树索引。不需要做任何特殊的事情。这将导致最佳索引,并且还将
uuid
字段存储为当前实用的紧凑格式。历史上的文物无论如何都不会比b树表现更好。请避免使用它们。在PostgreSQL 10上,它们已成为崩溃安全的,并且进行了一些性能改进,因此您不妨考虑一下。 br />如果由于某种原因而无法使用uuid
类型,则通常会在文本表示形式上创建b树,或者最好在uuid的bytea
表示形式上创建一个b树。评论
尽管有关哈希索引与b树的声明是一种普遍的看法,但我认为引用此类声明的来源会有所帮助。
–伏特
17年4月24日在20:30
从PostgreSQL 10开始,哈希索引现在是崩溃安全的。就是说,哈希索引只能与=一起使用,因此,如果需要任何其他运算符,则最好使用b树。
– rintaun
17-10-31在14:54
几年后,以我的经验,即使在Postgres 10中,哈希也没有比b树快得多,但是由于哈希索引占用的磁盘空间比b树少得多,因此在设置中哈希可能更快大索引成为一个问题,我觉得情况并非如此。好吧,现在我可以真正在v10中安全地使用它们了。
– sudo
18年1月30日,0:25
关于v10和v11中的哈希索引性能改进,有一些不错的文章:rhaas.blogspot.com/2017/09/…-amitkapila16.blogspot.com/2017/03/…
– Glenn Morton
18年6月30日下午6:00
#2 楼
BRIN指数?如果您使用基于时间的(版本1)UUID,则会生成它们,以便其值增加。在这种情况下BRIN是合适的。https://www.postgresql.org/docs/9.5/brin-intro.html:
BRIN表示块范围索引。 BRIN设计用于处理非常大的表,其中某些列与其在表中的物理位置具有某些自然相关性
。块范围是表中在物理上相邻的一组页面。对于每个
块范围,索引都会存储一些摘要信息。例如,存储商店销售订单的
表中可能有一个日期列,其中放置了每个订单
,并且大多数情况下,较早的
订单的条目会在表格中更早地显示以及一个存储ZIP
代码列的表可能会将一个城市的所有代码自然地组合在一起
。
BRIN索引可以通过常规位图索引扫描满足查询,并且
如果索引存储的summary
信息与查询条件一致,则将返回每个范围内所有页面中的所有元组。查询执行程序负责重新检查这些元组,并丢弃与查询条件不匹配的元组,换句话说,这些索引有损。由于BRIN索引非常小,因此与顺序扫描相比,扫描
索引只会增加很少的开销,但是
可以避免扫描表的大部分已知不包含匹配元组的部分。
BRIN索引将存储的特定数据以及该索引将能够满足的特定查询,这取决于为每一列选择的
运算符类索引。具有线性排序顺序的数据类型
可以具有运算符类,例如,存储每个块范围内的
最小值和最大值;
几何类型可能会将所有对象的边界框存储在
块范围内。
块范围的大小由索引创建时由pages_per_range存储参数确定。索引条目的数量等于页面中关系的大小除以pages_per_range的
选定值。因此,数字越小,
索引就越大(因为需要存储更多的索引
条目),但是同时存储的摘要数据可以更加精确和在索引扫描期间可以跳过更多数据块。
完美处理庞大且“大部分”有序的数据。
有关某些基准测试,请参见此文章:
https://www.percona.com/blog/2019/07/16/brin-index-for-postgresql-dont-forget-the-benefits/
1.3 GB的自然排序数据表(增加了时间戳)。然后他们在此数据库上生成了BRIN索引(pages_per_range = 32)和B树索引。然后他们比较了SELECT执行时间和索引的大小。他们得到了什么:
B树:
规划时间:22.225 ms执行时间:2.657 ms
public | testtab_date_idx |索引| postgres |测试表171 MB
BRIN:
规划时间:0.272 ms执行时间:87.703 ms
public | testtab_date_brin_idx |索引| postgres |测试表64 kB
同时没有索引,它将是:
规划时间:0.296 ms执行时间:1766.454 ms
只是给出顺序的感觉。
进一步讨论的重要一点是,在对这两个元素进行INSERT之后,索引更新的复杂性。对于BRIN来说它是O(1),因为您在存储器的下一个空闲空间上顺序写入并因此创建了新的BRIN条目,但是对于B树,众所周知,它是O(logN)(B树)(树越高,花费的时间越长)。
评论
我认为这是一个很好的答案。我不明白所有这些仇恨...
– Marcin Krupowicz
20-04-14在9:49
@Najib,您的编辑看起来不错,赢得了我的好评。我的最初评论应具有建设性,因为其初始形式的答案对解释链接没有多大作用。希望您能看到更好的解释,而不仅仅是在没有适当上下文的情况下粘贴链接。每个人都将从更好的答案中受益,这就是为什么我留下了最初的反馈。抱歉,您与社区的最初互动并没有什么不同,但是我希望您能坚持并让社区成为您想要成为的地方。
–约翰·埃斯布雷纳(John Eisbrener)
20年4月14日在19:36
另外,我在任何时候都没有对您的答案进行投票(只有在答案明显错误时才投票)。像您一样,我与社区的最初互动并非我所期望的,但我发现这里是获得信息和反馈的好地方。不要让少数投票者获得最好的帮助,我希望看到你坚持下去。
–约翰·埃斯布雷纳(John Eisbrener)
20-4-14在19:42
@JohnEisbrener谢谢!是的,我完全理解您,您的评论是正确的,我不应该写一个简短的简短答案,我意识到很快就会有所改善。但是,我认为指向系统在SO中的工作方式可能会得到改善,或者也许我太过认真了。无论如何,谢谢并希望我能有所作为。
–纳吉
20-4-14在22:09
不幸的是,没有符合RFC 4122的UUID版本/变体可以按词典顺序排序。即使是基于时间的生成器-如果您使用任何在线生成器并生成一些生成器,都可以看到。第一个十六进制段变化很快,而随后的十六进制段更稳定。这与您希望按字典顺序排序的值相反。这就是SQL Server具有不兼容的NEWSEQUENTIALID的原因。如果愿意为PostGres使用非RFC,那么可以对ULID进行分类。
– DharmaTurtle
20'八月22'在16:45
#3 楼
PostgreSQL中缺少哈希索引。 PostgreSQL知道它需要哈希索引,并且哈希索引的代码既旧又发霉,但是他们不会删除它,因为它们正在等待有人来检查哈希索引。看到此线程:http://www.postgresql.org/message-id/4407.1115698257@sss.pgh.pa.us
评论
在某些情况下,哈希索引在PostgreSQL中可以很好地工作,但是最近我发现,当我尝试对内置UUID数据类型主键和外键进行哈希索引优化时,它们导致查询不返回任何结果。哈希索引确实有很多好处,只要它们适用于所有数据类型,并且PostgreSQL开发人员知道这一点,他们就懒得自己修复它,并且将代码放置在原处,就像他们在为最终祈祷/祈祷一样。救主。
– derekm
16-4-10的15:58
我猜是有人救了哈希索引,因为哈希索引在数据分区中起着至关重要的作用,Pg10一直在关注该问题:wiki.postgresql.org/wiki/…但它们仍然不能提供理论上我所见过的一切在大学数据库课程中很有用;)
– sudo
18年1月30日,0:30
评论
我相信“联合数据库”是您所处情况的流行语。而且,是的,UUID是解决方案。这就是几十年前发明UUID的原因:无需分布式协调即可在分布式系统之间共享数据。几个月后:的确,Basil Bourque提出的“联合数据库”就是我们要的。我们不仅有多个服务器,而且还有一些客户端(可以将其视为联合数据库的更多部分)在脱机时创建ID。这就是我们使用UUID的原因。