mysql - 两个看似相同的数据库如何返回按不同列排序的结果?
问题描述
我有一个查询
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
and排序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
顺序传递行(但出于完全不同的原因)。
推荐阅读
- spring - 在不同的项目中共享 application.properties 文件
- python - 如何将控制台发送到手机的验证码放到一个pyqt5小部件中?
- javascript - 使用 Promise.all 嵌套 async/await
- javascript - Daterangepicker 在网页 ASP.NET MVC 中不起作用
- python-3.7 - Webscraper 没有使用 bs4 给出正确的结果
- java - 如何让这个 Java 代码格式化程序更漂亮
- mysql - Updating table by appending onto it several hundred rows
- javascript - Does calling setter of useState hook inside if statement imply BREAKING RULES OF HOOKS?
- excel - 有没有办法在我的可执行 (exe) 文件中嵌入一个 excel 文件?
- reactjs - 如何使用 nodemailer 更改邮件的发件人姓名?