查询表时的SQL性能

时间:2012-05-15 13:10:30

标签: 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

);

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

3 个答案:

答案 0 :(得分:3)

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

  • 您的t_users最好是自动增量无符号 int ID列。 (名字上的主键几乎总是一个坏主意。人们改名。人们有相同的名字。甚至国家有时更改名称!数字几乎总是最好的选择!)
  • 这样,您的t_posts可以引用该userID。加入现在正在快速发展。
  • 您甚至可以强制执行参照完整性:不存在的用户不能发布帖子。或者删除用户时,也会删除帖子。
  • 你的t_posts有一个ID主键列(好!),但它是varchar(坏!)。 INT更好。如果您需要,请BIGINT

您稍后会发现您的帖子可能包含多个主题(stackoverflow“tags”)。不要将它们放在varchar字段中。使用ID,说明和链接表“posts_to_topic”创建一个新表“主题”,将每个帖子链接到一个或多个主题。

索引

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

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

简化

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

但首先阅读关于索引的内容,关于什么,原因以及后来的方法。之后,您可以更深入地研究异常。

相同数据的多个表

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

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

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

考虑一下:如果您为每个用户创建帖子标题,请编写列出10个最常用主题的查询,以及每个主题的帖子数量。你必须为每张桌子命名!

答案 1 :(得分:3)

问题的真正答案前两个问题是“是”和“否”。 “是”,表格确实快速增长。而“不”这通常不会影响表现。

虽然您可以将表视为单个文件来扫描以查找结果,但SQL所做的远不止这些。几乎所有数据库都管理称为页表的内容,这意味着以下内容:

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

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

当涉及组合来自多个表的结果或聚合结果时,数据库在用于进行连接和聚合的算法中有许多人年的努力。在这种情况下你不太可能做得更好。

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

至于你的表架构,似乎你已经开始了,它很好。一般来说,我建议您的主键以表格命名并为整数。你的第一张表就是:

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

第二个表中的UserId被声明为int。作为为何更好的提示,用户可能希望不时更改其名称。

答案 2 :(得分:1)

  

将每个帖子拆分成新表会不会更好?

没有

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

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