PostgreSQL的ArrayField与ForeignKey?哪个是表演者?

我想设计一个电话簿应用程序,每个联系人可以有多个号码。有两种数据库设计:

    在每个号码
  1. 使用联系人外键。
  2. 将号码存储在每个联系人内部的ArrayField中。

哪种解决方案在生产中性能更高,为什么?

谢谢。

houyong888 回答:PostgreSQL的ArrayField与ForeignKey?哪个是表演者?

如果您在数组列上构建GIN索引,并且Django将以可以使用该索引的方式编写查询,那么两者的读取性能将非常相似。

性能差异不太可能成为该选择背后的驱动因素。例如,您是否需要电话号码后面的信息,而不仅是电话号码,例如添加电话的时间,电话的最后使用时间,电话是手机还是其他东西等。

数组列应该更快,因为它只需要查询一个索引和表,而不是两个。而且,它将更紧凑,因此更易于缓存。

另一方面,当estimating rare values时,您的数组列的统计估计值会出现问题,因为您可能会在这里遇到这个问题,因为可能不会有很多人共享电话号码。这种错误估计可能会对您的查询性能造成毁灭性的结果。例如,在一个小测试中,高估了几千行的行数导致它为单行查询启动并行工作程序,导致它比关闭并行化时慢约20倍,比使用并行化时慢10倍。不存在估计问题的外键表示形式。

例如:

create table contact as select md5(floor(random()*50000000)::text) as name,array_agg(floor(random()*100000000)::int) phones from generate_series(1,100000000) f(x) group by name;
vacuum analyze contact;
create index on contact using gin (phones );
explain analyze select * from contact where phones @> ARRAY[123456];
                                                                 QUERY PLAN                                                                 
--------------------------------------------------------------------------------------------------------------------------------------------
 Gather  (cost=3023.30..605045.19 rows=216167 width=63) (actual time=0.668..8.071 rows=2 loops=1)
   Workers Planned: 2
   Workers Launched: 2
   ->  Parallel Bitmap Heap Scan on contact  (cost=2023.30..582428.49 rows=90070 width=63) (actual time=0.106..0.110 rows=1 loops=3)
         Recheck Cond: (phones @> '{123456}'::integer[])
         Heap Blocks: exact=2
         ->  Bitmap Index Scan on contact_phones_idx  (cost=0.00..1969.25 rows=216167 width=0) (actual time=0.252..0.252 rows=2 loops=1)
               Index Cond: (phones @> '{123456}'::integer[])
 Planning Time: 0.820 ms
 Execution Time: 8.137 ms

您可以看到它估计将有216167行,但实际上只有2行。(为方便起见,我使用的是整数,而不是您可能会用于电话号码的文本字段,但这并没有改变任何基本的东西。)

如果这对您真的很重要,那么您应该使用自己的数据和体系结构进行测试并查看。这将取决于内存中哪些内容适合和哪些内容不适合,您正在执行哪种查询(您是否曾经批量查询数字?除了即将讨论的外键以外,将它们加入其他表中?),以及驱动程序/库处理具有数组类型的列/参数。

本文链接:https://www.f2er.com/3142976.html

大家都在问