【问题标题】:Mysql Performance Question - Essentially about normalizing efficiencyMysql 性能问题 - 本质上是关于规范化效率
【发布时间】:2010-04-02 18:39:00
【问题描述】:

只是一个关于数据库性能的简单问题。我将在下面概述我的网站目的作为背景。

我正在创建一个字典站点,它将用户定义的单词保存到数据库中。我想知道是否为每个用户创建一个单词表或保留一个大量单词表。该站点将用于整个学校,因此单个单词表会很大!

数据库结构如下:

一个用户表:

  • User_ID 主键,
  • 用户名
  • 首先
  • 最后
  • 密码
  • 电子邮件
  • 国家
  • 研究
  • 排名
  • 发送信息
  • 捐赠
  • 已加入
  • 上次登录
  • 登录
  • 正确
  • 尝试
  • 管理员
  • 活动

还有一个单词表:

  • User_ID 主键
  • 词汇
  • 拼写
  • 已定义
  • 已定义尝试
  • 拼写
  • 拼写尝试
  • 判刑
  • 已判刑

所以我要问的是,在性能方面,我是否应该在每个用户加入网站时为他们创建一个新表 - 每个用户随着时间的推移可能有成百上千的字词?还是拥有一张包含成千上万条记录并按 User_ID 过滤的海量表会更好。我认为我不会执行很多表连接。

我的直觉是为每个用户创建一个新表,但我想我会寻求专家的建议!提前致谢。

【问题讨论】:

  • 使用words.User_ID 列作为主键将限制每个用户最多一个字。要么使用words (User_ID, Word) 作为主键,要么在words.User_ID 上添加一个代理列作为主键和索引(在决定之前阅读stackoverflow.com/questions/532363/… 中建议的问题)。
  • 对于 SO 上的格式化帖子,您不需要添加段落标签。用四个空格缩进行以将它们格式化为代码。在行前加上“-”、“+”、“*”或“1.”来获取列表。单击帖子工具栏中的橙色问号以获取更多信息,这会将您带到stackoverflow.com/editing-help

标签: mysql database performance


【解决方案1】:

我认为您应该为所有用户和 user_id 使用一张表。

任何语言都没有那么多单词。这么多,我了解超过几百万。数据库在处理 1-2 百万条记录时运行良好,考虑到英语中的所有单词都超过 170.000,您不会很快达到那个水平

【讨论】:

    【解决方案2】:

    对于非常大的数据集,您可以通过将字典单词存储在每个用户的单独表中来获得更好的性能。

    但是,如果您想针对所有单词运行查询,例如,为了进行统计分析,编写查询来访问每个人的单词将会很困难。

    您可以将所有单词存储在同一个表中,然后如果出现性能问题,您始终可以对表进行分区,对用户 ID 进行哈希处理。查找 MySQL 的“分区”。它基本上为您将数据存储在单独的文件中,但允许您将所有数据保存在同一个逻辑表中,因此它仍然易于查询并保持正常形式。

    只要您为 user_id 上的单词编制索引,在相当长的一段时间内性能就不会下降,并且您的应用程序可能永远不会达到该阈值。

    从开发的角度来看,您可以通过保持简单并将所有单词存储在同一个表中来节省数小时的时间。由于您有未来的解决方法,因此如果出现性能问题,请保持简单并以最少的努力完成项目。

    【讨论】:

    • 对每个用户都有一个单独的表意味着每次查找用户的单词时,都必须打开一个新表并加载它的索引。如果您同时有许多用户,这意味着数据库必须花费大量时间来查找表,而不是查询它们所需的时间。 (单表缓存也更好)。
    • 您理想的数据库服务器有足够的内存来存储内存中的所有索引。
    【解决方案3】:

    性能方面,依赖于索引。如果某组列作为索引键的前缀,则index 通常可用于获取行而无需扫描表。一些查询不会使用索引(例如,如果某个列仅出现在某些 branches of an AND 中),但这些查询不包括简单地为给定用户查找单词;此外,对于每个用户都有一个表,这些查询将变得更加困难。

    CREATE TABLE users (
      id INT PRIMARY KEY AUTO_INCREMENT,
      username VARCHAR(32) UNIQUE,
      first VARCHAR(128) CHARACTER SET utf8 COLLATE utf8_unicode_ci,
      last VARCHAR(128) CHARACTER SET utf8 COLLATE utf8_unicode_ci,
      ...
    ) Engine=InnoDB;
    
    -- table of english words
    CREATE TABLE vocabulary (
      id INT PRIMARY KEY AUTO_INCREMENT,
      user_id INT,
      word VARCHAR(45), 
      ...
      -- searches for words of a given user should use `user_word`
      UNIQUE INDEX user_word (user_id, word),
      INDEX (word),
      FOREIGN KEY user (user_id) REFERENCES users (id) 
          ON DELETE CASCADE ON UPDATE CASCADE
    ) Engine=InnoDB CHARACTER SET utf8 COLLATE utf8_unicode_ci;
    

    题外话

    我们可以有surnamegiven_namemiddle_names 列,而不是firstlast 列,因为并非每种文化都放置given name first。当然,然后我们需要记录要打印的名称的顺序。另一种选择是为full name 和名字设置列。

    word 列有 45 个字符,以允许英语中最长的单词,即构造词“pneumonoultramicroscopicsilicovolcanoconiosis”。对于德语单词,我们至少需要 63 个字符。实际使用了“Rindfleischetikettierungsüberwachungsaufgabenübertragungsgesetz”,而不仅仅是尝试最长的单词。鉴于德语的性质,试图找到最长的单词长度是徒劳的。最好随意挑选一个。密钥大小上的limits(在 MySQL 5.0.17 及更高版本中为 3072 字节,在 MySQL 5.0.15 及更早版本中为 1023)为word 的大小设置了上限为 3066(5.0.15 中为 1018)字节,即在latin1_german1_ci(字典排序规则)中是 3066 (1018) 个字符,在 UTF-8 中是 1022 (339) 个字符。

    【讨论】:

    • 哇,这对每个人来说都是很棒的建议。非常感谢您的意见。看来我还有一些工作要做!
    猜你喜欢
    • 2011-01-29
    • 1970-01-01
    • 1970-01-01
    • 2011-03-03
    • 2013-11-14
    • 1970-01-01
    • 2011-01-27
    • 2015-04-08
    • 2021-11-09
    相关资源
    最近更新 更多