返回的MySQL查询结果是半随机的/不一致的有序

问题描述:

我正在使用使用proxysql的ndb集群设置。有4个mysql服务器,4个数据节点和2个管理节点。当我直接访问某个mysql服务器时会发生以下情况,所以我认为我可以安全地排除proxysql作为根本原因,但除此之外,我只是丢失了。返回的MySQL查询结果是半随机的/不一致的有序

这里有一个表我建立了帮助说明我的问题:

mysql> describe delain; 
+----------+-------------+------+-----+---------+----------------+ 
| Field | Type  | Null | Key | Default | Extra   | 
+----------+-------------+------+-----+---------+----------------+ 
| album_id | tinyint(2) | NO | PRI | NULL | auto_increment | 
| album | varchar(30) | YES |  | NULL |    | 
+----------+-------------+------+-----+---------+----------------+ 
2 rows in set (0.00 sec) 

它包含以下数据;请注意,我BY子句指定的顺序:

mysql> select * from delain order by album_id; 
+----------+-------------------------+ 
| album_id | album     | 
+----------+-------------------------+ 
|  1 | Lucidity    | 
|  2 | April Rain    | 
|  3 | We Are the Others  | 
|  4 | The Human Contradiction | 
|  5 | Moonbathers    | 
+----------+-------------------------+ 
5 rows in set (0.00 sec) 

如果我不指定一个ORDER子句,返回的结果是看似随意,像这样的:

mysql> select * from delain; 
+----------+-------------------------+ 
| album_id | album     | 
+----------+-------------------------+ 
|  3 | We Are the Others  | 
|  5 | Moonbathers    | 
|  1 | Lucidity    | 
|  2 | April Rain    | 
|  4 | The Human Contradiction | 
+----------+-------------------------+ 
5 rows in set (0.00 sec) 

当我重复查询( sans order clause)我每次都会得到不同的订单。它似乎并不是真正的随机,但是肯定的是,对我而言,这并不是什么可辨别的模式。

这是怎么发生的?我对mysql的经验总是默认的排序主要是根据主键,但这也是我第一次特别使用ndb集群;我不知道这里是否有区别,或者是否有配置文件中的设置被忽略或者什么。任何帮助是极大的赞赏!

+2

正如你刚才所意识到的,除非你指定了顺序,否则在每个数据库行中都不是有序的数据集。顺序可能因索引,群集,磁盘分区等而异。只是数据库以最有效的方式收集请求的数据。而且因为你没有设置'ORDER BY',所以他没有努力订购它,并且每次都可以得到不同的结果。 –

+0

这很有道理,并且当我尝试找出解决方案时遇到的其他信息与我之前遇到的其他信息相似,但根据我以前的经验,这似乎是违反直觉的。它肯定只是确认偏见,环境差异或类似情况,我想我不能依靠找到更广泛的,一刀切的解决方案。 非常感谢您的快速响应! – loungehead

+0

由于您没有指定'ORDER BY'子句,因此它不应该以您得到结果的顺序来打扰您。如果您需要订单,请使用'ORDER BY'子句,因为这是保证排序结果的唯一方法。一旦查询在并行线程中执行,结果顺序变得非常典型,因为查询的每次执行都不会有'ORDER BY'而变化。 –

这是标准的SQL行为。

https://mariadb.com/kb/en/library/sql-99/order-by-clause/说,在部分:

可以有选择地出现查询表达式后的ORDER BY子句:它指定的命令行应该从查询返回时(如果省略该子句,你的DBMS将返回以某种随机顺序排列的行)

(重点煤矿)

它会更准确的说,这将在一定任意顺序返回,而不是随机顺序列。随机意味着订单将从一次执行更改为下一次。

  • 对于InnoDB,顺序往往是行访问的索引顺序。它读取的索引不一定是主键。所以如果你知道内部的一些东西,那么顺序是不变的,并且有点可预测。但它不是随机的。

  • 在MyISAM的情况下,订单往往是行存储在表中的顺序,根据行插入的顺序不同,也取决于文件中存在空间的位置在行删除之后插入的时间。

  • 在NDB的情况下,我不太了解它的内部,所以我不能描述它的默认顺序的规则,但没有明确的ORDER BY也是如此,存储引擎是允许以任何顺序返回行。

+0

我想我可以非常自信地说,直到我们把这个集群放在一起,我总是使用InnoDB,根据你在第一个要点上说的话,它会解释为什么这会引发我这样的循环。那么,如果事情是这样的话,那就这样吧 - 我的代码将适应环境,而不是相反。 – loungehead

对于NDB,订单取决于在 的情况下的计时SELECT * from table;

来自表的SELECT *实现为并行 在数据节点及其数据库中的全表扫描 线程与一个 MySQL线程接收结果。

因此,使用筛选查询如 SELECT * from table where filter_column = 2; 筛选器在多个线程中并行进行评估。 这些线程中的每一个以任何 的顺序将行返回给MySQL线程,这取决于OS调度程序,网络和许多其他事情。所以没有默认排序,除非你使用ORDER BY。

因此对于NDB顺序是真正的随机性,而不仅仅是任意的。 您会在使用MTR的所有NDB测试套件中看到这一点, 查询主要使用来自表ORDER BY some_field的SELECT *