【问题标题】:MySQL Performance - 1 Million Records - Select Int before Text FieldMySQL 性能 - 100 万条记录 - 在文本字段之前选择 Int
【发布时间】:2014-10-24 17:37:39
【问题描述】:

显然,从 100 万条记录中选择一个文本字段会很慢,不推荐使用。这里有两种可能的解决方案。

  1. 将数据库拆分为每个用户自己的数据库或表,从而显着减少每个表中的总记录数。

  2. 执行 SQL SELECT 查询以匹配一个 INT,其中 INT 是用户 ID,然后匹配文本字段。

选项 1 将提供明显的性能提升。但选项 2 是否也能带来收益?在语句中,如果我们首先匹配 INT,这是否会将结果集缩小到仅匹配的记录,然后执行文本字段搜索。比如……

$user_id = 1001;
$domain_name = "mydomain.com";
$query = $database->prepare("SELECT * FROM domains_table WHERE user_id = $user_id && domain_name = $domain_name");

在上述查询中切换 user_id 和 domain_name 的位置会破坏性能。在这里首先匹配 user_id 有优势吗?

【问题讨论】:

  • EXPLAIN 对您的查询变体有何看法?你对它们进行了基准测试吗?您是否真的使用TEXT 字段作为域名(为什么),或者是VARCHAR?该字段是否已编入索引?
  • @DCoder 我使用 CHAR(36) 而不是 VARCHAR 来获得性能提升,因为这样会更快。同意吗?
  • 为什么你认为 100 万条记录会很慢并且不推荐? 100 万是非常小的 - 确保你有你的列索引。第一个选项听起来像是一场噩梦,甚至可能会导致性能损失。

标签: mysql sql database select


【解决方案1】:

一百万行的表不是很大。认真的。

如果您在 userdomain 字段上创建复合索引,那么您在问题中显示的查询将相当有效,而无需对使用整数标识符进行任何更改。

当然,整数标识符的效率略高如果您不必运行额外的查询来找出它们的值。

您花时间阅读有关 MySQL 中的索引和查询执行计划如何工作的信息将是值得的。

您的第一个选项(为单独的用户使用单独的表)比正确索引单个表要糟糕得多。这有很多原因,但其中最主要的原因是,当您开始拥有数千名用户时,它根本无法正常扩展。

【讨论】:

    【解决方案2】:

    你一直说事情是“显而易见的”。您是否对它们进行了测量以进行比较,或者您是否在做出假设?

    使用索引,可以非常快速地搜索字符串。如果您没有有索引,肯定比搜索整数要快得多。

    一旦你使用了索引,整数搜索和字符串搜索之间的区别几乎是难以察觉的。

    最好的索引是两列上的复合索引:

    ALTER TABLE domains_table ADD INDEX (user_id, domain_name);
    

    想想电话簿。这本书按姓氏排序,然后按名字排序。如果您搜索“Smith, John”,您可以轻松地将搜索范围缩小到所有 Smiths,然后在该子集中,姓名按名字排序,因此您可以轻松搜索所有名为 John 的人。这就是复合索引的工作原理。

    如果您没有索引,这就像从头到尾搜索整个电话簿。这称为表扫描,它变得越来越昂贵,与表的大小成正比。表的大小也会使索引查找变慢,但这次它的成本增加与表大小的对数成正比。

    在其他 cmets 中,您了解到优化器可以对 WHERE 子句中的术语重新排序,以匹配索引中列的顺序。这是真实的。这是查询优化器的工作,您可能使用的所有 RDBMS 产品(包括 MySQL)都足够聪明,可以做到这一点。

    您可能想阅读我的演示文稿How to Design Indexes, Really。或者我介绍这个演讲的视频:https://www.youtube.com/watch?v=ELR7-RdU9XU

    还有一个很棒的网站,其中包含许多关于索引的提示:Use the Index, Luke

    【讨论】:

      【解决方案3】:

      如果 user_id 上有索引,查询优化器将找出匹配它们的正确顺序。

      如果您为每个用户创建不同的数据库表,您只是将负载从数据库转移到文件系统。文件系统现在必须从大量文件中找到一个数据库表。更不用说当 MySQL 必须打开一个文件时会有开销,并且它可以打开的文件描述符的数量也有限制。

      长话短说:选项 1 不会带来性能提升。重新排序查询中的条件不会提供性能提升——查询优化器已经在没有你帮助的情况下计算出来了。唯一能提高性能的就是在 user_id 上有一个索引。

      编辑:想添加一些关于复合索引的内容。正如一些答案所建议的那样, (user_id, domain) 上的复合索引可能更适合您。它确实会进一步加快您与 user_id 和域匹配的查询。但是,索引不是免费的——每个索引都会减慢插入时间,添加新索引可能会减慢其他索引,因为所有索引都不能再保存在内存中。所以如果你知道你总是要查询 user_id, domain 你应该继续使用复合索引。但是,如果您的某些查询将是 user_id、domain 而其他查询将是 user_id 和 othercol、user_id 和 othercol2...那么您可能最好只使用 user_id 上的索引。

      【讨论】:

      • 出于兴趣:当 user_id 不是唯一标准时会发生什么? WHERE user_id = $user_id && domain_name = $domain_name"
      • 谢谢。那么你的意思是把它们都放在一个表中,首先匹配 INT id,然后是文本字段,然后对 ID 进行索引?
      • 您的标准是什么并不重要。查询优化器将适当地重新排序条件。如果您的条件是 `domain_name = $domain_name && user_id = "user_id"`,那么它很聪明,可以先通过 user_id 进行匹配,特别是如果您在 user_id 上有索引
      猜你喜欢
      • 2018-11-19
      • 1970-01-01
      • 2017-01-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-07-14
      • 1970-01-01
      • 2019-06-19
      相关资源
      最近更新 更多