连接约 40 个标准化表(200 列)以显示详细的用户配置文件。这个可以优化吗?

atk*_*yla 1 postgresql database-design

一个配置文件可以有多种配置文件类型。该配置文件可以有许多字段,这些字段都与查找表相关联。某些字段可以有多种选择。

\n\n
profile -> profile_date -> one relationship status, one zodiac, many languages, many countries traveled, many cuisines, many activities, ...\n\nprofile -> profile_network -> one company, one school, ...\n\nprofile -> ...\n
Run Code Online (Sandbox Code Playgroud)\n\n

字段的查找表如下所示:

\n\n
id  type\n1   \xe2\x99\x88 ARIES\n2   \xe2\x99\x89 TAURUS\n3   \xe2\x99\x8a GEMINI\n4   \xe2\x99\x8b CANCER\n5   \xe2\x99\x8c LEO\n6   \xe2\x99\x8d VIRGO\n7   \xe2\x99\x8e LIBRA\n8   \xe2\x99\x8f SCORPIO\n9   \xe2\x99\x90 SAGITTARIUS\n10  \xe2\x99\x91 CAPRICORN\n11  \xe2\x99\x92 AQUARIUS\n12  \xe2\x99\x93 PISCES\n
Run Code Online (Sandbox Code Playgroud)\n\n

如果该字段是单个选择,我们将加入查找表,然后就完成了。

\n\n
-> profile_date (zodiac_type_id) -> zodiac_type.id\n
Run Code Online (Sandbox Code Playgroud)\n\n

如果字段是多项选择,则中间有一个用于多对多的联接表。

\n\n
-> profile_date -> (profile_date_id) profile_date_languages (language_type_id) -> language_type.id\n
Run Code Online (Sandbox Code Playgroud)\n\n

此外,我还加入了其他类似的活动来获取他们的所有照片:

\n\n
profile -> personas -> photos\n
Run Code Online (Sandbox Code Playgroud)\n\n

此外,查询还可以过滤诸如彼此喜欢的人等内容。

\n\n

查询似乎开始表现不佳,只有少量的个人资料,比如少于 10 个。如果一个人有一个令人讨厌的个人资料,他们检查所有的多个选择,例如说每种语言,去过每个国家,它就会把数据库磨碎到如果他们的大型个人资料最终被获取,每个人的性能都会受到影响。

\n\n

这就是想法。您可以在此处查看更多字段:

\n\n

示例查询:\n https://pastebin.com/wug86Wrr

\n\n

示例查询计划:\n http://www.sharecsv.com/s/a6333a7f610e049dd81ebcfc19a4c02f/temp_file_limit_exceeded.csv

\n\n

用户将始终至少按 进行过滤profile.birth_date (age), profile.radius (geolocation)。付费用户可以按任何字段进行过滤。:)

\n\n

PostgreSQL 9.6

\n\n

我的一些想法是:

\n\n
    \n
  1. 优化这个查询(我不确定可以做什么,我主要想知道我是否只是在做一些非常愚蠢/不合理的事情)

  2. \n
  3. 现在,我每张卡加入许多表,因此初始加载速度较慢,但​​如果用户决定探索并且事情对他们来说是即时的,那么数据就在那里。我可以改为获取卡的最小预览(每张卡加入几个表),然后如果用户单击预览查看详细信息,则仅加入完整的配置文件(按 id 过滤的 1 张卡,许多/其余的连接)视图(但我觉得这不是最好的用户体验,因为用户现在每次单击更明显的配置文件时都必须等待加载)。我不确定这是否会有帮助,因为用户还可以按这些字段进行过滤,所以我相信我需要事先加入它们。

  4. \n
  5. 使用 ElasticSearch(我觉得除非有更多配置文件,否则我不需要这个?)我已经用 Algolia 做了类似的事情,它处理得很好,但我想这可以用 PostgreSQL 来完成。

  6. \n
\n

SQL*_*tor 5

选项 4 - 更正您的架构设计并停止使用“ID”或任何其他代理键,十二生肖表不是查找表。这是一种包含所有星座的关系,而区分星座的方式就是它们的名字,因此,关键应该是:

CREATE TABLE Zodiacs (Zodiac VARCHAR(11) PRIMARY KEY);
Run Code Online (Sandbox Code Playgroud)

使用 Zodiac 作为您的个人资料表中的外键,现在您根本不需要联接。对所有其他一对多(例如关系状态、公司、学校等)也这样做,您就节省了大部分连接。对于多对多,比如语言和国家,同样如此,现在每个关系只需要一个连接而不是两个。尝试一下,看看您的所有查询如何神奇地缩小 90%,并且性能提高几个数量级。您还将显式地维护唯一性并防止逻辑重复,并且您还将看到过滤器如何更好地执行数量级,因为优化器将能够正确评估实际值的分布,而不是另一个表中的某些随机 ID。

顺便说一句 - SQL 数据库中没有字段,只有列和行。这些是关系模型中元组和属性的对应部分

华泰

  • “人们提出的建议”基于 50 年前的神话,从磁带需要物理地址指针的时代开始。它已经变得如此普遍,以至于人们很少停下来思考它,并且认为这是理所当然的。它不仅仅适用于您的情况,它适用于地球上的每个关系数据库。观看此视频以获得更多答案:https://www.youtube.com/watch?v=r2MDDPDi_Pg (3认同)
  • 我想在这里提供最新情况。我重构了所有内容并消除了大部分连接。一切都如你所说,快了一个数量级。不再有性能问题。从现在开始,我将坚持“只有少数连接”的经验法则。 (3认同)