我是 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
);
这是一个有效的设计吗?每个用户的所有帖子都存储在同一个表中......所以如果我想查询所有主题为“编程”的评论,它需要查看每一个帖子,甚至通过具有不同主题的帖子,因为它们都存储在同一个表中....这也意味着如果我进行更复杂的查询,它们将以指数方式增长,我的磁盘上的表越大。 将每个帖子拆分到一个新表中不是更好吗?
最佳答案
设计是准有效的,但不完全:
- 你的
t_users
最好有一个未签名的autoincrement 整数 ID 列。 (名字的主键几乎总是一个坏主意。人们改变名字。人们有相同的名字。甚至国家有时也会改变名字!数字几乎总是最好的选择!) - 这样,您的
t_posts
就可以引用该用户 ID。现在加入速度非常快。 - 您甚至可以强制执行参照完整性:不存在的用户不能发帖。或者当用户被删除时,帖子也会被删除。
- 您的
t_posts
有一个 ID 主键列(好!),但它是 varchar(坏!)。 INT更好。BIGINT
如果你需要的话。
稍后您会发现您的帖子可能有多个主题(stackoverflow“标签”)。不要将它们 CSV 放在 varchar 字段中。创建一个包含 ID、描述和链接表“posts_to_topic”的新表“topics”,该表将每个帖子链接到一个或多个主题。
索引
您需要阅读的是索引。如果您想查询所有主题为“编程”的评论,您通常会在“主题 varchar(80)”列上有一个索引。这个索引很小(将其视为一个单独的表:它包含索引列和主键),因此您的 (R)DBMS 可以非常快速地搜索它(树结构)并获取它需要的所有主键。然后,根据您的选择,DBMS 会向您发送信息:
- 如果您只需要索引中已有的列,它可以从索引中获取所有内容。
- 如果您需要其他列,它现在只会实际访问 t_posts 表,并使用索引中的主键来访问行。
简化
我撒谎了。在最后一段中,我把它变得比实际情况简单得多。有一个优化器会查看查询并确定可以使用哪些索引。它将检查索引——取决于基数、表大小、它可能使用它的列,或者决定无论如何都要扫描表。如果您的表具有可变行长度,则获取第 X 行比所有行具有相同长度(无 VARCHAR)时慢得多。而这一切都取决于您使用什么 (R)DBMS(或在 MySQL 中,甚至取决于什么存储引擎)。
但首先要了解索引,了解什么、为什么,然后再了解如何。之后,您可以更深入地研究异常。
相同数据的多个表
这是初学者经常犯的错误,而且是双向的:
- “如果我们添加一列“TYPE”并将所有内容设为 varchar,我们就可以将所有内容放在一个表中!”
- “我们的数据库中只能有 10000 个表,table_1、table_2 等!”
阅读索引会告诉您为什么这在技术上是个坏主意,但它在逻辑尺度上也不那么优雅:一个表意味着代表一个实体(书籍。用户。帖子。页面) - 拆分这些将导致一些非常丑陋的查询。如果您问某人他们为什么这样做,原因通常是“为了速度”,而他们的决策列上的额外索引会产生相同的效果。
想一想:如果您为每个用户制作一个帖子标题,请编写列出 10 个最常用主题的查询,以及每个主题有多少帖子。您必须为每张 table 命名!
关于查询表时的 SQL 性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10601412/