mysql實現原理和機制「mysql隨機數生原理」

志在巔峰的攀登者,不會陶醉在沿途的某個腳印之中

1 前言

如下我這裡有一張抽題記錄表

MySql 你知道如何正確的取隨機數據嗎?

我需要隨機從中選4條數據,於是我會這樣寫(隨機排序,取前4個)

MySql 你知道如何正確的取隨機數據嗎?

執行時間 6.73秒,這個時間是絕對無法容忍的,你知道這個過程發生了什麼嗎???

2 MySql 的 rand 查詢過程 內存臨時表

select * from question_extracting order by rand() limit 4

上述這一句話先隨機排序,再取前4條,它的執行過程如下:

  • 第一步 創建一個臨時表,有兩個欄位,一個是double 類型使用A表示,另一個是 varchar(64) 類型 使用B表示,記為 欄位 W,需要注意的是這個表沒有建索引。
  • 第二步就是 從 上述 question_extracting 表中,按主鍵順序取出所有的行(因為這裡需要的是每行的所有數據),對於每一行數據,調用 rand() 函數生成一個大於 0 小於 1 的隨機小數,並把這個隨機小數和這一行數據 分別存入臨時表的 A 和 B 欄位中,需要掃描全表,如這裡的 4974098 行。
  1. 第三步就是在臨時表中按照欄位 A 排序,初始化 sort_buffer,sort_buffer 中會放兩個欄位,一個是 double 類型,用來放臨時表中的 A 欄位,另一個是整型,用來放臨時表中對應的數據的行號。
  2. 第四步就是在 sort_buffer 中根據 A 的值進行排序,排序完成後,取出前 4 個結果的位置信息,然後回到依次到內存臨時表中取出 對就的行信息 值,返回給 客戶端。
MySql 你知道如何正確的取隨機數據嗎?

在上述過程中,在第二步掃描了 question_extracting 全表 4974098 行 ,在第三步中也掃描了臨時表 4974098 行 ,然後在最後一步取數據又掃描了4行數據,所以這一次查詢總共掃描了 4974098 +4974098 + 4 次。

在上述這個過程中,order by rand() 使用了內存臨時表,內存臨時表排序的時候 使用了 rowid 排序方法,這個臨時表,沒有主鍵ID,由臨時生成的長度為 6 位元組的 rowid 來作為主鍵。

3 MySql 的 rand 查詢過程 磁碟臨時表

在 MySql 中,參數 tmp_table_size 限制了內存臨時表的大小,默認值是 16M,如果臨時表大小超過了 tmp_table_size,那麼內存臨時表就會轉成磁碟臨時表。

使用磁碟臨時表的時候,就是對一個沒有顯式索引的 InnoDB 表進行排序。

在這個過程中使用的是 MySQL 5.6 版本引入的優先隊列排序演算法,如我們上述的隨機取值,按照 優先隊列排序演算法 只需要取出 臨時表中最小的 4 個 A 值對應的數據就可以,這個過程可簡單描述如下:

  • 第一步 對於臨時表中這 4974098 個準備排序的 (A,rowid),先取前四行,構造成一個堆(可以理解為一個組)
  • 第二步 取下一個行 (R』,rowid』),跟當前堆裡面最大的 R 比較,如果 R』小於 R,把這個 (R,rowid) 從堆中去掉,換成 (R』,rowid』)
  • 重複第 2 步,直到第 4974098 個 (R』,rowid』) 完成比較
  • 最後一步就是 拿到這最小的4個值後,回到臨時表中取出對應的數據。

3 MySql 隨機排序的正確姿勢

隨機取一條數據,按照最開始的寫法如下:

MySql 你知道如何正確的取隨機數據嗎?

隨機演算法的正確姿勢

MySql 你知道如何正確的取隨機數據嗎?

你並沒有看錯,這就是正確的寫法


select max(id),min(id) into @A,@B from question_extracting ;

set @C= floor((@A-@B+1)*rand() + @B);

select * from question_extracting where id >= @C limit 1;

可描述如下:

  • 第一步 取得這個表的主鍵 id 的最大值 M 和最小值 N,這個過程不需要掃描表
  • 第二步 用隨機函數生成一個最大值到最小值之間的數 C = (A-B)*rand() + B;
  • 第三步 取不小於 C 的第一個 ID 的行

完畢

不局限于思維,不局限於語言限制,才是編程的最高境界。

推薦閱讀:MySql 你真的會使用字元串索引嗎?

原創文章,作者:投稿專員,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/210948.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
投稿專員的頭像投稿專員
上一篇 2024-12-08 16:26
下一篇 2024-12-08 16:26

相關推薦

發表回復

登錄後才能評論