2012-05-30 3 views
3

У меня есть очень большой стол (более 10 млн или даже 100 млн записей), с этой схемой:Выберите случайную строку для каждой группы в большой таблице

ид Int первичный ключ, правило Int

и хотите выберите случайную запись для каждого правила. Я попробовал этот запрос, но это занимает много времени (TreeNode этого имя таблицы):

SELECT tmp.id,tmp.rule FROM treenode 
LEFT JOIN (SELECT * FROM treenode ORDER BY RAND()) tmp ON (treenode.rule = tmp.rule) 
GROUP BY tmp.rule; 

Хранение данных как Хеш в памяти занимает огромную память. Другим вариантом является выборка каждой группы из базы данных и выбор случайной записи. Опять же, поскольку количество групп составляет около 100 тыс., Отправка этого количества запросов в базу данных занимает много времени.

обновление: Я могу добавить, что эта таблица заполняется только один раз, и на ней не будет никаких изменений. Идентификатор и правило имеют в них дыры.

+0

В зависимости от специфики ваших данных возможны различные оптимизации. прочитайте его: http://jan.kneschke.de/projects/mysql/order-by-rand/ – goat

+0

Это больше о получении случайной записи из таблицы не для группы –

ответ

0

Я узнал, что через все записи требуется меньше времени, чем этот запрос. Поэтому я добавил столбец как правило * max (id) + id и создал индекс на нем (должен ли я использовать представление?).

бегаю следующий запрос:

SELECT id,rule,temp FROM treenode where temp>? ORDER BY temp LIMIT 0,100000; 

На клиенте пройти через все возвращенные записи и заполнить буфер. Всякий раз, когда правило изменяется, я выбираю случайный элемент из буфера и очищаю его (поместите индекс = 0). Затем я снова запускаю запрос? как значение последнего возвращаемого значения темпа.

2

Возможно, мне что-то не хватает, но не соответствует запросу, эквивалентному вашему запросу?

SELECT * FROM (SELECT * FROM treenode ORDER BY RAND()) x GROUP BY x.rule; 

Это будет быстрее, так как нет объединения.

+0

Да, это быстрее, спасибо. Но все же требуется время на большой стол –