【问题标题】:How can two seemingly identical databases return results sorted by different columns?两个看似相同的数据库如何返回按不同列排序的结果?
【发布时间】:2019-04-30 20:48:55
【问题描述】:

我有一个查询

SELECT r.id
     , r.account_id
     , r.name
     , r.bucket_id
     , r.description
     , r.development
     , r.created_at
     , r.priority
  FROM realms r
 WHERE r.account_id = 3;

我在两个具有相同索引的不同表上运行它,一个结果按r.idr.created_at 排序(两种方式都相同),另一个结果按r.name 排序。这怎么可能?

通过 MySQL Workbench 中的表检查器查看,两者的索引都是:

+---------------------------+-------+-----+-----------------+
| key                       |Type   |Uni  | Columns         |
+ --------------------------+-------+-----+-----------------+
| PRIMARY                   | BTREE | YES | id              |
| realms_account_id_name_UQ | BTREE | YES | account_id,name |
| realms_account_id_IX      | BTREE | NO  | account_id      |
| realms_bucket_id_IX       | BTREE | NO  | bucket_id       |
+---------------------------+-------+-----+-----------------+

我认为是索引决定了输入的顺序,当我在两者之间切换时,屏幕甚至没有闪烁。如果他们两个的主键都是id,为什么一个显示按名称排序的结果?

【问题讨论】:

  • sql表中的行没有内在的顺序,所以这个问题没有意义
  • 让我们把“无意义”变成关于使用ORDER BY 并了解索引如何工作的课程。

标签: mysql sorting indexing


【解决方案1】:

如果您的SELECT 中没有ORDER BY 子句,系统可以随心所欲。时期。句号。

现在,我将解释可能发生了什么。

首先,优化器将分析索引、数据类型、统计信息等,并决定如何执行查询。您可以通过EXPLAIN SELECT ... 了解此操作。它会说它可能使用哪个索引。

我看到两个索引是合理的——两个以account_id 开头。任何一个都可以。可能优化器在两台机器上的统计数据略有不同,导致它在一台机器上选择一个索引,而在另一台机器上选择另一个。

使用INDEX(account_id, name)的分析。该索引是 account_ids 和名称对的有序列表。在使用该索引的机器上,它将 BTree 索引向下钻取到account_id = 3 的第一个条目,然后向前扫描。这为您提供了由name 排序的结果。

使用INDEX(account_id)的分析。 InnoDB,为了找到数据,将PRIMARY KEY 列添加到每个二级索引上。因此,该索引实际上是INDEX(account_id, id)。在使用该索引的机器上,它将 BTree 索引向下钻取到account_id = 3 的第一个条目,然后向前扫描。这为您提供了由id 排序的结果。

第三种可能性很常见,值得注意。如果有很多行带有account_id = 3,优化器将决定避开索引并简单地读取数据。由于数据是根据PRIMARY KEY 存储的,因此它会再次以id 的顺序传递行(但出于完全不同的原因)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-12-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多