• Выборка случайного поля в MySQL

    winnie
    @winnie
    Безусловно. Вот результаты тестов:

    nettsundere@tsundere:~/Desktop/test$ ruby compare.rb
    Введите пароль, пожалуйста:
    Благодарю вас!
    Для 10 элементов результаты показаны следующие:
    Было: 0.00035 сек. в среднем
    Стало: 0.000275 сек. в среднем
    Стало (если бы max сохранили в redis или memcached): 0.0001375 сек. в среднем
    Для 100 элементов результаты показаны следующие:
    Было: 0.0004375 сек. в среднем
    Стало: 0.0002875 сек. в среднем
    Стало (если бы max сохранили в redis или memcached): 0.00015 сек. в среднем
    Для 1000 элементов результаты показаны следующие:
    Было: 0.0011375 сек. в среднем
    Стало: 0.0003125 сек. в среднем
    Стало (если бы max сохранили в redis или memcached): 0.0001625 сек. в среднем
    Для 10000 элементов результаты показаны следующие:
    Было: 0.0097125 сек. в среднем
    Стало: 0.00035 сек. в среднем
    Стало (если бы max сохранили в redis или memcached): 0.000175 сек. в среднем

    Было — это с ORDER BY RAND()
    Стало — это два запроса
    Стало (если бы… сохранили) — это если мы max не будем вычислять каждый раз, а достанем из кэша.

    Код теста: gist.github.com/1371692

    Первый запрос можно и нужно кэшировать (что видно из результатов (стало и стало с сохранением max), где я кэширование лишь изобразил, дабы не писать сложный тест, но видно, что запрос на max(id) достаточно тяжелый, чтобы его всякий раз выполнять). Записать max(id) можно даже в специальную таблицу для кэша, если не имеется возможности использовать redis или memcached. Обновлять придётся лишь при добавлении новых записей и при удалении.
    Ну или просто оставить как есть, если устраивает.
  • Выборка случайного поля в MySQL

    winnie
    @winnie
    Ошибся, у записей с id=5,6,7,8 будет вероятность P=1/8
  • Выборка случайного поля в MySQL

    winnie
    @winnie
    Пусть мы имеем множество ключей с id:
    1,2,3,4,5,6,7,8
    и таким методом выбираем случайную запись.
    Количество «выпадений» каждого кортежа с id будет практически равно при большом количестве выборок — идеальный случай. При очень большом количестве выборок. Тут мы говорим, что всякая выборка будет равновероятна (P=1/8 для каждого id) (Закон Больших Чисел из теории вероятности). Это как бросать монетку бесконечное количество раз — примерно будет пополам орла и решки.

    А теперь представим, что мы удалили записи с id 1,2,3
    И теперь имеем 4,5,6,7,8
    А число, что генерируется всё ещё лежит в пределе [1, 8] и по закону больших чисел будет равновероятно выдавать значения от 1 до 8, но поскольку мы обращаемся к БД с «дырками», то вероятность выпадения 4 повышается, повышается в четыре раза (всякое значение функции получения случайного кортежа, в которой сгенерировалось случайное от 1 до 4 в результате даст нам запись с id = 4). Тут мы говорим, что равновероятность не соблюдается и вероятность появления записи с id=4 равна P=4/8=1/2, а у записей c id=5,6,7,8 вероятность P=1/4

    Далее представим, что записей, допустим, тысяча. Вероятность выпадения одного элемента в идеальном случае — 1/1000. Ну, допустим, пару элементов перед ним удалили и она стала 3/1000, когда у других элементов будет меньше. Для многих такая разница будет бедой, а для многих — не будет, мы же не корабли в космос запускаем. На деле разница в таких вероятностях проявится только в статистике, если размер дыр не планируется соразмерный с количеством записей вообще.

    Устранять дыры можно уже потом, когда перестанет радовать неравномерность, по крону. Да только придется ли вообще это делать? Вот где вопрос. Если удаляются записи не огромными пачками последовательными, то всё будет радовать пользователя.
  • Выборка случайного поля в MySQL

    winnie
    @winnie
    А это и не нужно скорее всего. Тут какая-нибудь «случайная статья» же, или товар, например. Ну можно часа в четыре утра устранить погрешность за прошлый день по крону — никто не пострадает скорее всего. Считаю архитектурные изменения излишними. Редко на ZF пишут вроде энтерпрайз, где тервер строгий необходим.
  • redis - много независимых серверов на запись -> 1 агрегирующий

    winnie
    @winnie
    Ой, у вас наверное агрегирующий вне локальной сети находится, из вопроса не понял сразу. Тогда мой вариант не подходит.
  • Git. Измененные файлы между двумя коммитами

    winnie
    @winnie
    Идентификатор должен быть начального коммита указан.