Mysql

在 MySQL 中隨機排序所有 ID 的快速方法

  • April 8, 2021

我需要將 random IDs 分配給一個表。因此,我創建了一個映射表

CREATE TABLE t2
(
ID int(11) unsigned NOT NULL AUTO_INCREMENT,
SourceID int(11) unsigned NOT NULL,
UNIQUE INDEX(SourceID),
PRIMARY KEY(ID)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE utf8_general_ci KEY_BLOCK_SIZE=1

然後將ID主表中的 s添加t1

INSERT IGNORE INTO t2 (SourceID) SELECT ID FROM t1 ORDER BY RAND()

例如,想像t1是學生的測試結果,我們不想將學生 ID (t1.ID) 透露給審閱者(用於匿名審閱)。然後,我們使用儲存在 中的新 ID 顯示每條記錄t2

SELECT t2.ID AS NewID, t1.results FROM t1 JOIN t2 ON t1.ID=t2.SourceID

問題是t1數千萬行並且RAND()非常非常慢。

我在這裡不需要完美RAND();只是分配 new IDs(以某種方式隨機排列)。你能想出一種更快的查詢方法嗎?

我通過檢查性能做了很多實驗。它可能會幫助其他人。

最快的方法(到目前為止)是在 SQL 查詢之外進行隨機重新排列。

SELECT ID INTO OUTFILE '/tmp/id.csv' 
   FIELDS TERMINATED BY ',' LINES TERMINATED BY '\n' FROM t1

然後

shuf -o /tmp/id.csv < /tmp/id.csv

最後是快速的INSERT一步

LOAD DATA LOCAL INFILE '/tmp/id.csv' INTO TABLE t2 
   FIELDS TERMINATED BY ',' LINES TERMINATED BY '\n' (SourceID)

可能的伎倆。

創建中間表。將您的ID從 t1 複製到其中。添加從值計算一些雜湊的虛擬生成列id,並將其索引。將此表用作插入源,通過創建的索引表達式添加排序,並強制它(沒有索引提示,由於 100% 行選擇,它可能會被忽略。從另一邊來看,它必須使用,因為它是覆蓋的)。

在那裡可以找到一個例子。

如果您認為它BINARY(16)太長,那麼您可以剪下一部分校驗和值並將其從十六進製字元串轉換為例如 INT。當然,該索引實際上不會接近唯一,但據我了解,這並沒有提及。

PS。當然,在將數據複製到 temptable 的階段會耗費大量時間,但插入本身必須很快。我無法預測整個過程是否會更快 - 測試它。

引用自:https://dba.stackexchange.com/questions/289469