【问题标题】:Many tables or rows, which one is more efficient in SQL?很多表或行,在 SQL 中哪一个更高效?
【发布时间】:2025-12-04 08:05:01
【问题描述】:

我正在构建一个程序,用于存储公司的新闻标题及其来自各种来源的时间戳。

假设公司的数量是 1000。它就像 Apple、Google、Microsoft.. 等。

所以我可以考虑两个选项。

  1. 一个包含许多行的表(上面的代码只是一个示例)。

    CREATE TABLE news
    (
        news_id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
        company VARCHAR(10) NOT NULL,
        timestamp TIMESTAMP NOT NULL,
        source TEXT NOT NULL,
        content TEXT NOT NULL,
        ...
    )
    
    // I also can make company and timestamp as primary keys,
       and news_id will be unique key.*
    
  2. 1000 个表

    CREATE TABLE news_apple // and news_google, news_microsoft, news_...(x 1000)
    (
        news_id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
        timestamp TIMESTAMP NOT NULL,
        source TEXT NOT NULL,
        content TEXT NOT NULL,
        ...
    )
    

大多数时候,我会找到某家公司的新闻。假设每家公司有超过 10000 条新闻。我想知道如果我在第一个选项中使用“WHERE”子句,它会比第二个选项慢。

哪一个在性能方面更高效,为什么?

【问题讨论】:

  • 更多行。这就是关系数据库的设计目的。具有相同结构的多个表通常表示设计不佳。
  • 您考虑过基于 nosql 的解决方案吗?
  • @GordonLinoff 你能给我更详细的解释吗?
  • @rmayer06 是的,但这不是一个选项。
  • 这一次,我在风格问题上完全同意@GordonLinoff :)。添加更多行比添加更多列/表要容易 1000 倍。查询很快就变成了噩梦,试图将相似的表“融合”回主表,就好像它们是同一张表一样。添加列以区分行的类型。

标签: mysql sql database schema relation


【解决方案1】:

制作一张包含所有公司的表,但使用外键!您可以通过数字识别每家公司,并拥有另一个查找表,其中包含每个数字和公司的字符串。喜欢:

CREATE TABLE news
(
news_id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
company_id INT 11,
timestamp TIMESTAMP NOT NULL,
source TEXT NOT NULL,
content TEXT NOT NULL,
...
)

CREATE TABLE companies
(
company_id INT 11
company_name VARCHAR(10)
)

使用外键约束使其明确:http://dev.mysql.com/doc/refman/5.6/en/create-table-foreign-keys.html

这样您将通过重复存储数字而不是字符串来节省空间,您的索引会更小,并且您的查找会更快。

【讨论】:

  • 感谢您的回复。我知道可以使用外键分隔表,但我想知道上述两个特定选项的性能。
  • 这取决于您要执行的查询类型。如果您只想查询来自特定新闻源的记录,那么将它们拆分为多个表会更好。但是,如果您想查询特定内容的所有新闻来源,那么拥有一个索引良好的表会表现得更好,因为您不必查询多个表并聚合结果。
【解决方案2】:

我在许多表方面的经验,目前在一家拥有 6000 多个表并且还在不断增长的公司工作,但管理许多表的难度很大。好处是您可以减少表中的行数(我在其他公司有 3000 万行),这很好 - 但前提是您的所有表都有一个可管理的解决方案。

例如:这 6000 多张桌子实际上是带有房间号 ID (data_room#_hotelID) 的酒店,因此我可以编写存储过程、bash 或 php 脚本来处理它们。

另一方面,多行更简单,因为您要处理的表更少,但是您需要开始创造性地研究如何提取数据。您肯定希望在 SQL WHERE 子句上添加索引,但这很明显。

我过去用来管理大型表的选项是:

1) 以有意义的方式(如按字母顺序)插入具有自动增量的数据 - 但看到您的数据变化很大,这不是一个好的选择

2) 将表加载到内存中 - 我不知道您将其托管在哪里,但我在内存中使用 MySQL。我只知道两种方法:一种是在 MySQL 本身上设置它,另一种是有一个内存驱动器(使用一些计算机的 ram)并将 MySQL 和它的数据移动到安装的驱动器(我已经也使用了闪存驱动器)。

您还需要考虑是否更频繁地插入或选择数据。

总结一下:

  • 如果您选择创建多个表,请确保它们没有保存大量数据并且您可以管理它们。

  • 如果您使用更少的表和更多的行,请使用索引、RAM 驱动器、缓存来加快从大型表中获取数据的过程。

这是我的两分钱,希望对你有帮助!

【讨论】:

    【解决方案3】:

    关系数据库旨在为每个表存储许多行。有很多机制可以促进大表,例如:

    • 对任意字段组合的索引以加快搜索速度
    • 页面缓存,因此常用页面保留在内存中
    • 垂直分区(列式数据库)以进一步加快请求速度
    • 哈希联接和分组依据等高级算法(至少在 MySQL 以外的数据库中)
    • 使用多个处理器和磁盘来处理查询

    在将数据放入单个表中时,有一件事情比较困难,那就是安全性。而且,事实上,在某些情况下,这是一个主要问题,基本上要求数据放在单独的表中。这些应用程序很少见。

    举个例子,说明在多个表中存储数据有多糟糕,假设在您的系统中,每个公司都有一条记录,并将其存储在一个表中。该记录存储有关公司的信息——例如名称、地址等。调用是 100 字节的信息。

    在您的架构中,每个“公司”都有一个单独的表,因此每个表只有一行。该记录将驻留在一个数据页上。一个数据页可能是 16 KB,因此您浪费了大约 15.9 KB 来存储这些数据。存储 1000 条这样的记录占用 16 MB,而不是大约 7 页(112 KB)。这可能会对性能造成重大影响。

    此外,对于多个表,您没有考虑维护所有表和确保不同表中数据正确性的挑战。维护更新需要应用于数千个表,而不是少数。

    【讨论】:

    • 啊!这就是我要找的。谢谢。
    最近更新 更多