我有一个查询
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.id
和排序r.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
为什么一个显示按名称排序的结果?
如果您的 中没有ORDER BY
子句SELECT
,系统可以随心所欲。时期。句号。
现在,我将解释可能发生的事情。
首先,优化器会分析索引、数据类型、统计信息等,并决定如何执行查询。您可以通过执行 了解此操作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
顺序传递行(但出于完全不同的原因)。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句