order by rand () создает проблемы для больших постов - PullRequest
1 голос
/ 10 января 2011

У меня есть этот код, этот код вызывает проблемы и так много времени для выполнения, чтобы показать СЛУЧАЙНЫЕ сообщения из БД:

$totalrows = 10;

$sql = "SELECT 
 posts.Tags as tags, 
 posts.OwnerUserId as postsid, 
 posts.Id as postid, 
 posts.Body as body, 
 posts.Title as title, 
 users.Id as userid, 
 users.DisplayName as usersname  
FROM posts 
JOIN users ON posts.OwnerUserId = users.Id 
WHERE posts.Title != '' order by rand() asc limit " .  $totalrows;

$r = mysql_query($sql) or die(mysql_error());

Скажите, пожалуйста, что мне следует изменить, чтобы более случайные сообщения отображались быстрее?

С уважением, Dan

Ответы [ 5 ]

2 голосов
/ 10 января 2011
1 голос
/ 10 января 2011
 $sql = "select posts.id from posts where posts.title != '' order by rand() asc limit " . $totalrows;

 $result = mysql_query($sql) or die(mysql_error());

 $tmpArray = array();

 while($row = mysql_fetch_array($result)){
    $tmpArray[] = $row['id']; // This will add all items to array
 }

 $csvResult = implode(',',$tmpArray);

 $sql = " select posts.*, users.* From posts join users on posts.owneruserid  = user.id where posts.id in (" . $csvResult . ")";

 $r = mysql_query($sql) or  die(mysql_error());

Пожалуйста, проверьте все опечатки и имена столбцов.

0 голосов
/ 10 января 2011

Еще один способ

$totalrows = 10;

$sql = "SELECT 
 posts.Tags as tags, 
 posts.OwnerUserId as postsid, 
 posts.Id as postid, 
 posts.Body as body, 
 posts.Title as title, 
 users.Id as userid, 
 users.DisplayName as usersname  
FROM posts 
JOIN users ON posts.OwnerUserId = users.Id 
JOIN (select posts.id from posts where posts.title != '' order by rand() asc limit " . $totalrows .") AS tmp_result
ON (posts.Id = tmp_result.Id)";


$r = mysql_query($sql) or die(mysql_error());

Хм, я не знаю, ускорит ли это ваш сценарий: D теперь все зависит от ваших записей.

0 голосов
/ 10 января 2011

Проблема с вашим кодом.

  1. Вам нужно получить 10 случайных сообщений
  2. Вам необходимо получить имя человека, который разместил
  3. Они должны быть случайными, но соединение требует времени.

Я предлагаю вам разделить их,

$sql = "select posts.id where posts.title != '' order by rand() asc limit " . $totalrows;

выполнить результат, а затем взорвать результат в формате CSV $csvResult = 2,3,4,5 эти числа являются идентификаторами случайных сообщений. В вашем втором запросе

$sql = " select posts.*, users.* From posts join users on posts.owneruserid = user.id where posts.id in (" . $csvResult . ");

$r = mysql_query($sql) or die(mysql_error());

Надеюсь, это уменьшит время.

0 голосов
/ 10 января 2011

У меня нет средств для тестирования этого прямо сейчас, но это должно дать довольно равномерное распределение, и я сомневаюсь, что скорость будет проблемой. Выберите несколько случайных чисел ОДИН РАЗ в PHP и выполните простую операцию модуля, которая должна быть «достаточно случайной», чтобы упорядочить ваши строки.

Если точные цифры, которые я выбрал, не дают хороших результатов, вы, вероятно, можете выбрать те, которые будут.

$totalrows = 10;  
$m = rand(31,61);
$k = randint(10,20);
$offset = rand(200,500) % $m;

$sql = ... "ORDER BY (post_id + $offset + $k*(post_id MOD 8)) MOD $m LIMIT $totalRows";

$r = mysql_query($sql) or die(mysql_error()); 

Если это все еще слишком медленно, вы можете попробовать добавить некоторую базовую случайность в предложение WHERE в качестве «грубого» фильтра, чтобы упорядочить не так много строк. Однако имейте в виду, что это должно быть проще, чем то, что вы делаете в ORDER BY, или вы просто будете снова выполнять те же медленные операции.

Дайте мне знать, если это работает для вас, мне любопытно, и я бы хотел сам проверить это на SQL. Дистрибутивы выглядят довольно хорошо, когда я пытаюсь сделать что-то подобное в Python для набора идентификаторов 1-20000, но это ничего не говорит мне о скорости выполнения в SQL

...