вопрос по запросам к БД в php

12
S
На сайте с 25.11.2005
Offline
82
snk
#11

Чем order by rand() плох? :)

Он на не большом кол-ве записей тормозить вроде не должен.

Dreammaker:
Один из нормальных путей это:

1) получить MIN(id), MAX(id);

2) сгенерировать 50 штук чисел между этими значениями;

3) Сделать или 50 запросов, или сделать id = IN(число, число, число, число ....), или через UNION. Всё это ориентируясь на последовательность полученных в п.2 значений

4) полученные результаты перевести в массив, а его в свою очередь сериализовать и положить в кеш, обновлять вышеуказанным способом раз в сутки.

5) Доставать массив разсериализовывать и доставать оттуда случайным образом 5 значений, выводить их.

Моменты на которые стоит обратить внимание:

1) если в п.3 есть ещё какие-то WHERE, то обязательно нужно делать индексы, а лучше составные.
2) мы можем получить не 50, а меньше значений - так как некоторые посты могут быть удалены, в скрипте нужно учитывать это.
3) этот пункт для тех, кто может заметить, что здесь псевдослучайность - обычный пользователь врядли будет смотреть больше 10 страниц, а постоянные посетители врядли будут смотреть на случайные посты.

В целом данный способ испробован и успешно работает, а почему б ему не работать :), на сайте с несколькими десятками тысяч уников (от 30 до 80, в среднем - 40-50К), записей где-то около 5-6 тысяч. Проблемы были только один раз, поэтому я и настаиваю на составных индексах, тогда всплыла проблема как раз с этим.

p.s. общий принцип похож на описанный выше modobaks'ом.
Заставь свой сайт работать на тебя. Реально работает! (http://tinyurl.com/cqkpeg)
N_MONax
На сайте с 22.08.2007
Offline
112
#12

Dreammaker, боже, как сложно...

snk:
Чем order by rand() плох?

Только тем, что он переберёт ВСЕ значения.

Лично я на базе в 400K записей юзаю следующую конструкцию:

SELECT * FROM table WHERE RAND()<0.001 ORDER BY RAND() LIMIT X,

где число 0.001 подбирается опытным путём.

Полёт нормальный. Выполнение - доли секунды.

N_MONax добавил 16.05.2009 в 04:44

Если к этому добавить кеширование и большую посещаемость (как вариант в данном случае, постоянно сохранять полученные выборки в файлах или базе, а потом "подмешивать" через раз уже "готовые" выборки) то вообще всё шоколадно будет.

Полный спектр услуг в интернете. Быстро, Качественно, Дорого. Пишите в личку.
Dreammaker
На сайте с 20.04.2006
Offline
569
#13
N_MONax:
Только тем, что он переберёт ВСЕ значения.

EXPLAIN SELECT * FROM dle_post WHERE RAND( ) < 0.001 ORDER BY RAND( ) LIMIT 5

id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE dle_post ALL NULL NULL NULL NULL 4338 Using where; Using temporary; Using filesort

А ваш способ прям не просматривает все записи :D

N
На сайте с 06.05.2007
Offline
419
#14

В данном случае explain со случайными функциями не сможет оценить вероятности , поэтому лучше вызывать сразу после запроса show status like 'handler%'; . Увидите Handler_read_rnd_next равный числу строк.

Кнопка вызова админа ()
Dreammaker
На сайте с 20.04.2006
Offline
569
#15
SELECT * FROM dle_post WHERE RAND( ) < 0.001 ORDER BY RAND( ) LIMIT 5;
show status like 'handler%';
Variable_name Value
Handler_commit 0
Handler_delete 0
Handler_discover 0
Handler_prepare 0
Handler_read_first 0
Handler_read_key 0
Handler_read_next 0
Handler_read_prev 0
Handler_read_rnd 5
Handler_read_rnd_next 4359
Handler_rollback 0
Handler_savepoint 0
Handler_savepoint_rollback 0
Handler_update 0
Handler_write 18

То есть, получается просматриваются все записи или почти все.

N_MONax
На сайте с 22.08.2007
Offline
112
#16

Dreammaker, Возможно. Я просто предложил свой способ.

У меня он работает в 10-тки раз быстрее, нежели order by rand(). Исследованиями мускул-запросов я никогда не занимался :)

S
На сайте с 27.03.2009
Offline
29
#17

Быстрее будет без сортировки, как уже тут предлагали.

1. Генерим рандом число в диапазоне количества записей - X.

2. В лимите говорим выводить столькото записей ( например 5) с позиции X.

ПС: не забываем про коридор из (в нашем случае 5-ти записей) т.е. диапазон генерации снижаем на кол-во выводимых записей.

12

Авторизуйтесь или зарегистрируйтесь, чтобы оставить комментарий