查询表时的 SQL 性能

标签 sql postgresql

我是 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/

相关文章:

c# - 生成的 LINQ 类中的继承?

postgresql - 使用 Aerogear Unified Post Server + Docker + Postgres 获取 "ERROR: relation PRIMARY already exists"

ruby-on-rails - 外键约束确实会导致 N+1 查询但没有约束,预加载工作正常

java - "=?"在 SQL 查询中使用时代表什么

sql - 查找表中存在的命名列

sql - Apache Drill 对现有 Hadoop 集群中的其他 Hadoop 生态系统成员有什么负面影响吗?

mysql - 如何优化查询?我能读懂什么? (如果可以的话,用俄语,或英语)

sql - 为什么 Postgresql 搜索 Text 索引比 Int 索引快?

sql - 如何在 PostgreSQL 事务中获取实时?

postgresql - 如何使用 SpringBoot + JPA 存储 PostgreSQL jsonb?