0

我是 SQL 新手,不了解性能影响。似乎 SQL 数据库将所有内容都存储在一个地方。这是否意味着表格变得非常大,非常快?这不会影响性能吗?

Stackoverflow 模型示例,但带有线程注释:

CREATE TABLE t_users (
   name varchar(80) primary key,
   email varchar(80)

);

CREATE TABLE t_posts (
   id varchar(80) primary key,
   userid varchar(80) references t_users(name),
   title varchar(80),
   description text,
   topic varchar(80),
   path text

);

这是一个有效的设计吗?每个用户的所有帖子都存储在同一个表中......因此,如果我想查询所有具有“编程”主题的评论,则需要查看每一个帖子,即使是具有不同主题的帖子,因为它们都存储在同一个表中......这也意味着如果我进行更复杂的查询,它们将成倍增长,因为我的磁盘表越大。将每个帖子拆分到一个新表中不是更好吗?

4

3 回答 3

3

该设计是准有效的,但不是完全有效的:

  • t_users最好有一个自动增量unsigned int ID 列。(名字的主键几乎总是一个坏主意。人们改变名字。人们有相同的名字。甚至国家有时也会改变名字!数字几乎总是最好的选择!)
  • 这样,您t_posts可以参考该用户 ID。现在连接速度非常快。
  • 您甚至可以强制执行参照完整性:不存在的用户不能发布任何帖子。或者当用户被删除时,帖子也会被删除。
  • t_posts有一个 ID 主键列(好!),但它是 varchar(坏!)。INT更好。BIGINT如果你需要它。

您稍后会发现您的帖子可能有多个主题(stackoverflow“标签”)。不要将它们 CSV 放在 varchar 字段中。创建一个新表“主题”,其中包含 ID、描述和链接表“posts_to_topic”,将每个帖子链接到一个或多个主题。

索引

您需要阅读的是索引。如果您想查询所有主题为“programming”的评论,您通常会在“topic varchar(80)”列上有一个索引。该索引很小(将其视为一个单独的表:它包含索引列和主键),因此您的 (R)DBMS 可以非常快速地搜索它(树结构)并获取它需要的所有主键。然后,根据您的选择,DBMS 会向您发送信息:

  • 如果您只需要索引中已有的列,它可以从索引中获取所有内容。
  • 如果您需要其他列,它现在只会实际访问 t_posts 表,并使用索引中的主键来访问行。

简化

我撒了谎。在最后一段中,我让这一切变得更加简单。有一个优化器会查看查询并确定可以使用哪些索引。它将检查索引——取决于基数、表大小、它可能使用它的列,或者决定扫描表。如果您的表具有可变的行长度,则获取第 X 行比所有行都具有相同长度(无 VARCHAR)时要慢得多。而这一切都取决于您使用什么 (R)DBMS(或在 MySQL 中,甚至取决于什么存储引擎)。

但是首先阅读索引,关于什么,为什么,然后是如何。之后,您可以更深入地研究异常。

同一数据的多个表

这是初学者经常犯的错误,它们是双向的:

  • “如果我们添加一列“TYPE”并使所有内容变为 varchar,我们可以将所有内容放在一个表中!”
  • “我们的数据库中只能有 10000 个表,table_1、table_2 等等!”

阅读索引会告诉你为什么这在技术上是一个坏主意,但在逻辑上它也不那么优雅:一个表意味着一个实体(书籍。用户。帖子。页面) - 拆分这些会导致一些非常难看查询。如果你问某人为什么这样做,原因通常是“为了速度”,而他们的决策列上的额外索引也会产生相同的效果。

想一想:如果您为每个用户创建一个帖子标题,请编写列出 10 个最常用主题的查询,以及每个主题有多少个帖子。您必须为每张桌子命名!

于 2012-05-15T13:14:19.287 回答
3

您问题前两个问题的真正答案是“是”和“否”。“是的”,表格确实增长得很快。“不”这通常不会影响性能。

尽管您可以将表视为您扫描以查找结果的单个文件,但 SQL 的作用远不止于此。几乎所有数据库都管理称为页表的东西,这意味着以下内容:

  • 读取表格后,如果它可以放入内存,它将一直留在那里,直到需要移出。这大大加快了对表的进一步查询。
  • 加载页表通常与处理异步操作。

这两点本身很难(但并非不可能)在大多数编程语言中实现。此外,SQL 为您提供索引和表分区,可以进一步加快单个表的处理速度。最后,大多数版本的 SQL 支持几乎所有功能的多个处理器/线程。

当涉及到组合来自多个表的结果或聚合结果时,数据库在进行连接和聚合的算法方面付出了很多人年的努力。在这种情况下,您不太可能做得更好。

而且,这些功能没有涉及关系数据库的许多其他功能,例如强制数据一致性、备份和恢复数据、保证修改等。

至于您的表架构,您似乎正在入门并且很好。一般来说,我建议您的主键以表格命名并且是整数。您的第一张桌子将是:

CREATE TABLE users (
    UserId int primary key,
    name varchar(80),
    email varchar(80)
); 

第二个表中的 UserId 被声明为 int。作为提示为什么这样做更好,用户可能希望不时更改他们的名字。

于 2012-05-15T13:27:39.370 回答
1

将每个帖子拆分到一个新表中不是更好吗?

不。

如果您的帖子在不同的表中,那么您必须查询数百甚至数千个不同的表才能找到所有数据。

更不用说,除了数据(大小相同,无论它在哪个表中)之外,您还有表本身的开销。

于 2012-05-15T13:14:11.447 回答