從 mysql 中隨機取出千筆資料 (別用 order by rand())

前陣子看到這篇提到別在 mysql 裡用 order by rand()。若有 1m 筆資料, order by rand() 相當於呼叫 1m 次 rand() 再做排序。可以想見速度不會快。若想取出隨機的資料, 視情況有不同的取代方案。注意 django 裡的 order_by('?') 轉換後的 sql 就是 order by rand(), 別用它。

若 table 有個流水號 id, 且沒有刪過資料, 可以先產生 1 ~ max(id) 之間的數字, 再用 id in (...) 取出隨機的資料。用 Django 的 ORM 來表示大概長這樣:
from django.db.models import Max
import random

mid = MyTable.objects.aggregate(Max('id'))['id__max']
ids = random.sample(xrange(1, mid + 1), 1000)
MyTable.objects.filter(id__in=ids)  # 隨機取出 1000 筆資料

若有刪過資料的話, 可能就多取幾筆最後再取前 1000 筆, 或是先取出所有 id 存下來再 sample 吧。

我自己測的結果, 百萬筆的資料用 order_by('?') 要數秒, 但改用 id__in 的寫法則是瞬殺。

留言

這個網誌中的熱門文章

(C/C++ ) 如何在 Linux 上使用自行編譯的第三方函式庫

熟悉系統工具好處多多

virtualbox 使用 USB 裝置