代码之家  ›  专栏  ›  技术社区  ›  erotsppa

规范化这个表更快吗?

  •  0
  • erotsppa  · 技术社区  · 16 年前

    我有两张桌子,像这样:

    表人:
    VARCHAR名称
    整数年龄

    表消息
    VARCHAR消息
    VARCHAR名称

    消息表中有数百个插入和删除操作,查询如下:

    insert into Message VALUES ('Hello there', 'John');
    delete from Message where name = 'John';
    

    我的问题是,在人中添加一个ID字段并在消息中引用用户作为ID是否值得?以下查询会更快吗?

    FIRST - select id from User where name = 'John'
    THEN - delete from Message where id = $id
    

    我起初认为,通过搜索ID进行插入和删除要比通过字符进行搜索快。但是有多快?速度增加是否会抵消由于需要对用户表进行额外查询以查找ID而带来的性能损失?

    11 回复  |  直到 16 年前
        1
  •  5
  •   tekBlues    16 年前

    如您所说,额外的查询将使其速度稍慢(当然,这取决于名称的长度、数据库类型等)。

    但是,当用户更改其名称、删除用户等时会发生什么情况?那种设计会给你带来很多痛苦。最好是规范化,不管这个小小的性能问题,

        2
  •  4
  •   HLGEM    16 年前

    一个人的名字从来不是一个好的主键,因为名字不是唯一的。它们会随着时间的推移而改变。使用代理键要好得多(是的,int上的join通常更快,而且在许多数据库中可以加入删除stampent,而不是使用较慢的子查询),特别是因为名称往往比几个字符长。

        3
  •  4
  •   Jeffrey Kemp    16 年前

    你的设计是 已经 规范化,假设您对people.name有唯一的约束,并且message.name和people.name之间存在引用完整性约束。

    这并不是标准化的问题——如果你想让人们改变他们的名字,你就有一个性能和可伸缩性的问题(需要更新消息表中所有相关的行)。

    如果人们从来没有在你的系统中更改过他们的名字,那么这不是问题。在这种情况下,名称几乎和ID一样好——尽管有些DBMS在使用索引数字而不是索引字符串(?)时可能表现得更好。.

    删除的性能是另一个问题-我想说,如果您已经有一个唯一的名称,那么按名称删除将比按ID进行查找(或加入)删除要快-但同样,您要做自己的基准测试。

        4
  •  3
  •   Binary Worrier    16 年前

    速度快吗?然而,只有分析才能说明问题。…

    更好的做法是在Person上放置一个ID列,在ID上放置一个从消息到人的外键约束(即假定所有消息只能传递给Person表中的人)。

    您仍然可以在一个语句中删除消息

    delete from Message where id IN (select id from Person where Name = 'John')
    

    数据库将对此进行优化,使其比两个语句快得多(即比单独的select和delete语句快得多)。

    您可以在外键约束上指定级联删除,以便在删除某个人时,该人的所有消息也会自动删除。

    更多信息请参见此处 Foreign Keys

        5
  •  1
  •   kemiller2002    16 年前

    如果大多数名称都很短(不是15到20个字符长),并且表被正确索引,那么从ID字段接收到的速度性能将是微不足道的。

        6
  •  1
  •   Bernard Chen    16 年前

    您不需要执行额外的查询。你可以这样做:

    DELETE FROM Message 
    INNER JOIN User 
      ON Message.id = User.id 
    WHERE User.name = 'John'
    
        7
  •  1
  •   ahains    16 年前

    根据我的经验,网站后端的用户表是那些几乎100%时间都保存在内存中的表之一。它对于任何活动都是非常重要的,因此它永远不会脱离页面缓冲区。所以我肯定会使用userid来处理所有类似的引用。

        8
  •  1
  •   Matt    16 年前

    对你 准确的 用如此小的模式来转储原始文件的内容的问题 信息 表中,非规范化会更快。查询计划将更小,更容易优化,并且不会有连接开销。

    一般来说,这要复杂得多。

    这是否是正确的做法是一个问题。为此,从规范化设计开始,但如果有令人信服的理由,那么要愿意并准备去规范化。有时,反规范化的原因是合理的,尽管通常标准化数据的收益抵消了任何性能损失。

    规范化数据更容易维护,而且通常更灵活。为了灵活性,有一个数字键可以让你有多个名字相同的人。可以向添加更多字段 很容易。在不扫描所有人的情况下运行一个报告来查看系统中的所有人更容易。 信息 .

    但性能可能是一个因素。考虑到这两个表中的数据,数据库有几个关于如何联接的选项。它可以使用 信息 作为基表,以及连接的方式将影响事物(嵌套循环、哈希连接、排序/合并等)。

    但除此之外,归一化实际上可以 更快 . 如果你的模式比你描述的更复杂怎么办?让我们说你的 表中有50个与人力资源相关的字段, 信息 表只有一个20个字符的消息字段。如果你有两个人的情况,但是有10万条消息,那么非规范化的速度实际上会更快。这是因为I/O是数据库的最大限制因素。如果要在一个查询中转储所有数据,则规范化数据将只获取这50个字段一次,并且 信息 表将密集地填充数据。在非规范化版本中,每行 信息 将包含51个字段,您将大幅增加I/O的数量以获得相同的结果。

        9
  •  0
  •   Cade Roux    16 年前

    在你得到一个好的设计之前,你不需要担心优化。

    现在,我想很难说这是否是一个不切实际的玩具问题,但通常情况下,你会在设计时考虑到一个主键和外键的关系,而这个键是 非常 不太可能是瓦查尔。

    它可能是一个guid,也可能是一个int,但是不管是哪种方式,你至少要在它上面有一个非聚集索引,或者在它上面有一个聚集索引,并且你要在像用户名这样的重要数据上有一个非聚集索引,所以最终你整个系统的性能(而不仅仅是这个删除)将依赖于一个稳定的规范化的desi。gn和这些表的良好索引策略。

        10
  •  0
  •   Hakan Winther    16 年前

    这是关于IO和可维护性的。如果varchar包含的字节少于4个,那么如果使用varchar而不是整数,查询将更快。但这并不是一个很大的进步,如果你需要改变名字,你会失去很多的表现!消息表中的每一行都需要更新(如删除和插入)。

    如果使用整数,则只存储4个字节作为对用户表的引用。如果在用户表中对id和name使用覆盖索引,那么这只是一个很小的开销。用户表可能会保留在缓存中,这取决于用户表中需要多少行以及您拥有多少内存。在这种情况下,您将有一个逻辑扫描,而不是慢得多的物理扫描。

        11
  •  0
  •   Jon Onstott    16 年前

    另一个注意事项:不要忘记在要加入表的列上放置索引,如果它们还没有索引的话。