【问题标题】:PK Query on M2M RelationM2M关系PK查询
【发布时间】:2022-01-02 10:14:59
【问题描述】:

我正在阅读 Neo4j,一个图形数据库,以及它与关系模型的比较。这是它在如何查询与单个用户 here 关联的“部门”的 M2M 连接时提到的一件事:

我想,如果我事先知道我只是逐行查找单个 PK 并且该用户可能少于 5 个部门,我会编写如下查询:

SELECT name FROM department WHERE department_id IN (
  SELECT department_id FROM PersonDepartment WHERE user_id IN (
    SELECT pk FROM Person WHERE name='Alice' # assume unique name
  )
)

我确信以更常见的“连接格式”编写此内容会被 RDBMS 优化为更接近上述内容,但我使用上述内容只是为了展示上述查询看起来几乎不需要是时候执行了,还是我错了?另一方面,以更简洁的 Cypher 格式编写上述内容:[p:Person{name:"Alice"}]-[:BELONGS_TO]->[d:Department] 更易于读写。

【问题讨论】:

  • 您说得对,正确的索引选择 Alice 的部门在 RDBMS 中是微不足道的。
  • 问题是什么? PS我们应该如何处理“几乎没有时间执行”?引用的文字没有说明实施,所以你反对什么? PS Neo4j 文献中说了很多关于关系模型的废话。 PS请use text, not images/links, for text--including tables & ERDs。转述或引用其他文本。只提供您需要的东西并将其与您的问题联系起来。仅将图像用于无法表达为文本或增强文本的内容。在图片中包含图例/键和说明。

标签: sql relational-database graph-databases


【解决方案1】:

初步

解决一些混淆问题的问题,以便我们能够以直截了当的方式回答问题。

  1. 图形中的文字简介

    • 这是完全不诚实的,典型的稻草人论点,用来贬低他反对的东西,并提升他的支持。他将 Relational 方法设置为它不是的东西(1960 年代的记录归档系统,IDs 作为“主键”),然后将其删除
    • 哎呀,他毁了自己的混合物,他的稻草人
    • 关系方法保持不变,不受影响
    • 然而,未受过教育的人会感到困惑。
  2. ID 字段作为“主键”
    关系模型明确禁止IDs,这是物理的。 PK 必须是“由数据组成”,这是逻辑的。

    • 此外,文件包含重复的IDs不提供唯一性,这是RM中要求的)李>
    • IDs 使 DML 代码复杂化,并强制更多 JOINs(在等效的关系数据库中不需要),亲爱的教授指望在他的稻草人的竖立中
    • 需要删除IDs,并需要实施适当的关系键
    • 逻辑的关系完整性(与物理的引用完整性不同)丢失,不可能
    • Relational schema for a book graph 中的详细信息。
  3. 没有一个头脑正常的人会以这种方式遍历这三张表,更不用说开处方了。

    • 他正在使用程序代码,例如在 CURSOR 中,它是反关系的,而且速度非常慢
    • RM和SQL都是基于集合论的,所以使用集合动词,比如SELECT,只选择你需要的
    • 命题是一个单一的集合,一个单一的SELECT 满足它。

问题

我想,如果我事先知道我只是逐个 PK 查找单个行,并且该用户可能少于 5 个部门,我会编写如下查询:...

绝对不是。即使是IDs

  • 每个表中的总体是不相关的(PK 具有唯一索引)
  • 让我们假设有 10,000 个人; 10,000 个部门; 16,000,000 个人部门
  • 在建模或编写 DML 代码时绝不应考虑性能
    • 只有在某些代码性能不佳时才应考虑,以期对其进行改进。

除了为了澄清您的问题之外,可以忽略该代码。

我确信以更常见的“连接格式”编写此内容会被 RDBMS 优化

是的。

  • 有了一个真正的 SQL 平台,它会在很多层面上做很多事情重新优化:解析;确定查询计划;统计方面的考虑;等等

  • 使用免费软件“SQLs”,它会做一个米老鼠版本(最好的情况),而根本没有(最坏的情况)。这就是为什么性能是无处不在的考虑因素,但这是不正常的;不合格。

进入更接近上述的东西

绝对不是。那是狗的早餐。它将创建一个非常优雅和优化的查询计划,然后是一个分层查询树(运行时可执行文件,可以共享)。

但我使用上面的只是为了展示上面的查询看起来几乎不需要时间来执行,还是我错了?

不,你是对的。从某种意义上说,无论是在 RFS 上运行的可怕代码示例,还是在关系数据库上运行的正确代码,都将在毫秒内执行,“几乎没有时间”。

关系数据模型

如果您希望使用关系数据库(没有IDs,正确的关系键)评估他在提议中的意图(爱丽丝为哪些部门工作),而不像他的稻草人那样不诚实,我们需要一个数据型号。

  • 我所有的模型都在IDEF1X 中呈现,这是关系数据建模的唯一标准。 (不能使用 ERD。)
  • IDEF1X Introduction 是必读。

代码很简单。

SELECT  NameFirst,
        DepartmentCode
    FROM Person P
        JOIN Employee E ON P.PersonNo = E.EmployeeNo
    WHERE NameFirst = "Alice"

这段代码可能会产生更有意义的结果集,它仍然是一个单一的、简单的SELECT

SELECT  NameLast,
        NameFirst,
        D.Name,
        EmploymentDate
    FROM Person P
        JOIN Employee E ON P.PersonNo = E.EmployeeNo
        JOIN Department D ON E.DepartmentCode = D.DepartmentCode
    WHERE NameFirst = "Alice"

评论

关于“没有 ID,正确的密钥”的一个问题 - PersonNo 的行为方式与自动递增 PK 识别人的方式不同吗?

是的。

除了AUTOINCREMENT/IDENTITY 列存在可怕的维护问题,因此我们不允许它们在生产中使用,因此我们不允许它们在不用于生产的开发中使用。

INSERT 的替代方案是:

... 
PersonNo = ( 
SELECT MAX( PersonNo ) + 1
    FROM Person
    )
...
  • 当然,对于高性能 OLTP,还有其他方法。
  • 永远不要使用 Oracle 方法,它是一个记录文件,每个文件都为其他文件保存一个下一个序列号。

如果我们使用 PK 必须“由数据组成”并且没有 SS# 或一些唯一识别人员代码,那么它只是组合了一堆东西:名字+姓氏+出生地+出生日期(或任何组合将提供足够的粒度以保证唯一性)

是的。 IDEF1X Introduction 详细解答了这个问题,请阅读。

简答...

  1. 这是一个真正的代理,而不是 RecordID(被错误地称为代理)。
  2. 唯一的理由是当
    • 自然 PK 太长(此处为 7 列和 120 多个字节),无法作为 FK 携带到从属表中,
    • 该表是数据层次结构的顶部,因此不会受到 Codd 的关系模型中规定的访问路径独立性破坏。这里的用法是正确的。

从技术上讲,代理或RecordID) 违反了关系键范式。正确放置的代理不会违反访问路径独立规则(超出要访问的违规),而RecordID 总是这样做。用户看不到代理或RecordID,因为它不是数据。

另外,请注意(LastName, FirstName, Initial, Birthdate, BirthCountry, BirthState, BirthPlace)是用于识别个人的既定国际惯例(不是标准)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-22
    • 1970-01-01
    • 1970-01-01
    • 2013-08-19
    • 2023-02-17
    • 1970-01-01
    相关资源
    最近更新 更多