2010年4月28日 星期三

從 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++ 能否用 memcpy 複製 class / struct 的資料?

答案是: POD (plain old data) type 可以。POD type 可和 C 互通, CPP Reference POD Type 的介紹: Specifies that the type is POD (Plain Old Data) type. Thi...