M2M关系PK查询

PK Query on M2M Relation

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

我会想如果我事先知道我只是逐行查找一个 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
  )
)

我确信用更常见的 'join format' 写这个会被 RDBMS 优化成更接近上面的东西,但我使用上面的只是为了展示上面的查询看起来如何几乎没有时间执行,还是我错了?另一方面,将上面的代码写成更简洁的 Cypher 格式:[p:Person{name:"Alice"}]-[:BELONGS_TO]->[d:Department] 更易于读写。

初步

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

  1. 图形中的文字简介

    • 完全不诚实,典型的稻草人论调,用来贬低他反对的东西,抬高他支持的东西。他把关系方法当作它不是的东西(1960 年代的记录归档系统,IDs 作为“主键”),然后把它取下来
    • 哇哦,他毁了自己的作品,他的稻草人
    • 关系方法仍然存在,不受影响
    • 然而,未受教育的人会感到困惑。
  2. ID 字段作为“主键”
    关系模型明确禁止IDs,它们是物理的。 PK必须是“由数据组成”的,这是Logical的。

    • 此外,该文件包含重复的 IDs 不提供 唯一性,这是 RM)
    • IDs 使 DML 代码复杂化,并强制执行更多 JOINs(在等效的关系数据库中不需要),亲爱的教授正在指望,在他的稻草人
    • 需要删除 IDs,并且需要实施适当的关系键
    • 逻辑的关系完整性(与物理的参照完整性不同)已丢失,不可能
    • 中的详细信息。
  3. 任何头脑正常的人都不会以这种方式逐步完成这三个 table,更不用说开处方了。

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

问题

I would think though if I knew beforehand I'm just looking up a single row-by-PK and there are less than 5 departments likely for that user, I would write the query as follows: ...

绝对不是。即使 IDs

  • 每个table中的人口无关(PK具有唯一索引)
  • 假设有 10,000 人; 10,000 个部门; 16,000,000 人部门
  • 建模或编写 DML 代码时永远不应考虑性能
    • 只有当某些代码表现不佳时才应考虑,以期改进它。

除非是为了澄清您的问题,否则可以忽略该代码。

I'm sure writing this in the more common 'join format' would be optimized by the RDBMS

是的。

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

  • 使用免费软件“SQLs”,它的米老鼠版(最好)和 none(最差)。这就是为什么性能是考虑因素,无处不在,但这是不正常的;不合标准。

into something closer to the above

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

but I'm using the above just to show how the above query seems like it would take almost no time to execute, or am I wrong here?

不,你是对的。从某种意义上说,无论是在 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"

评论

One question regarding the "no IDs, proper keys" -- doesn't the PersonNo act the same way as would an autoincrementing PK to identify a person?

是的。

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

INSERT 的备选方案是:

... 
PersonNo = ( 
SELECT MAX( PersonNo ) + 1
    FROM Person
    )
...
  • 当然,对于高性能的OLTP,还有其他的方法。
  • 切勿使用 Oracle 方法,它是一个记录文件,每个记录都包含其他文件的下一个序号。

If we went with PK must be "made up from the data" and no SS# or some uniquely-identifying-person-code, it'd then be just combining a bunch of stuff: FirstName+LastName+BirthPlace+Birthdate (or whatever combination would give enough granularity to guarantee uniqueness)

是的。 IDEF1X Introduction里面回答的很详细,请看

简答...

  1. 这是一个真正的代理人,而不是RecordID(被误称为代理人)。
  2. 唯一的理由是什么时候
    • 自然 PK 太长(这里有 7 列和 120+ 字节),无法作为 FK 进入下属 tables,
    • table 是数据层次结构的顶层,因此不会像 Codd 的 Relational 中规定的那样遭受 访问路径独立性 破坏型号。这在此处的用法中是正确的。

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

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