mysql排序規則引發的一系列問題
背景
- 項目中提出需求,獲取到業務數據之後,需要隨機抽選五條,即mysql隨機獲取表中5條數據。
mysql默認的排序方式
- mysql常用存儲引擎MyISAM和InnoDB
查看錶的存儲引擎:show create table xxx
- 從MySQL5.5.5以後,InnoDB是默認引擎
- myisam引擎表在沒有任何的刪除,修改操作下,執行 select 不帶order by,那麼會按照插入順序進行排序。
- 對於innodb引擎表來說,在相同的情況下,select 不帶order by,會根據主鍵來排序,從小到大
mysql默認排序真的是按照主鍵進行排序的嗎?
- 建表:
CREATE TABLE `test` (
`id` int(10) NOT NULL AUTO_INCREMENT,
`name` char(100) DEFAULT NULL,
`age` char(5) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `age` (`age`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8
- 準備測試數據:
INSERT INTO test VALUES(NULL,'張三','5');
INSERT INTO test VALUES(NULL,'李四','15');
INSERT INTO test VALUES(NULL,'王五','5');
INSERT INTO test VALUES(NULL,'趙信','15');
INSERT INTO test VALUES(NULL,'德瑪','20');
INSERT INTO test VALUES(NULL,'皇子','5');
INSERT INTO test VALUES(NULL,'木木','17');
INSERT INTO test VALUES(NULL,'好漢','22');
INSERT INTO test VALUES(NULL,'水滸','18');
INSERT INTO test VALUES(NULL,'小芳','17');
INSERT INTO test VALUES(NULL,'老王','5');
-
執行查詢sql
SELECT * FROM test LIMIT 5
,反覆執行,發現結果一樣,的確是按照主鍵,從小到大排序 -
繼續,執行查詢sql
select id,age from test limit 5
,返回的結果和第一次完全不同。 -
分析
-- 所有列
explain select * from test limit 5;
id select_type table type possible_keys key key_len ref rows Extra
-- ----------- ----- ---- ------------- ------ ------- ------ ---- -----
1 SIMPLE test ALL (null) (null) (null) (null) 11
-- 僅id,age列
explain select id,age from test limit 5;
id select_type table type possible_keys key key_len ref rows Extra
-- ----------- ----- ----- ------------- --- ------- ------ ---- -----------
1 SIMPLE test index (null) age 16 (null) 11 Using index
分析結果:第一個查詢語句是沒有使用到任何的索引的,而第二個查詢則是使用了age作爲索引
- 結論:可以看出,mysql在不給定order by條件的時候,得到的數據結果的順序是跟查詢列有關的。因爲在不同的查詢列的時候,可能會使用到不同的索引條件。Mysql在使用不同索引的時候,得到的數據順序是不一樣的。這個可能就跟Mysql的索引建立機制,以及索引的使用有關了。
如何隨機獲取更優?
- 方案一:
SELECT * FROM table_name ORDER BY RAND() LIMIT 10;
- 方案一結論:效率最慢,在 ORDER BY從句裏面不能使用RAND()函數,因爲這樣會導致數據列被多次掃描,導致效率相當相當的低!
- 最優方案請參考:MySQL 中隨機選擇10條記錄