Я оптимизирую множество существующих запросов в моем проекте. Решение Quassnoi помогло мне значительно ускорить запросы! Однако мне трудно включить указанное решение во все запросы, особенно для сложных запросов, включающих множество подзапросов в нескольких больших таблицах.
Так что я использую менее оптимизированное решение. По сути, он работает так же, как и решение Кассного.
SELECT accomodation.ac_id,
accomodation.ac_status,
accomodation.ac_name,
accomodation.ac_status,
accomodation.ac_images
FROM accomodation, accomodation_category
WHERE accomodation.ac_status != 'draft'
AND accomodation.ac_category = accomodation_category.acat_id
AND accomodation_category.acat_slug != 'vendeglatohely'
AND ac_images != 'b:0;'
AND rand() <= $size * $factor / [accomodation_table_row_count]
LIMIT $size
$size * $factor / [accomodation_table_row_count]
определяет вероятность выбора случайной строки. Rand () сгенерирует случайное число. Строка будет выбрана, если rand () меньше или равна вероятности. Это эффективно выполняет случайный выбор, чтобы ограничить размер таблицы. Так как есть вероятность, что он вернет меньше заданного предельного числа, нам нужно увеличить вероятность, чтобы убедиться, что мы выбираем достаточно строк. Следовательно, мы умножаем размер $ на $ фактор (обычно я устанавливаю $ factor = 2, в большинстве случаев работает). Наконец мы делаем limit $size
Проблема сейчас в том, чтобы решить гостиничный_стол_в__счету .
Если мы знаем размер таблицы, мы можем жестко закодировать размер таблицы. Это будет работать быстрее всего, но, очевидно, это не идеально. Если вы используете Myisam, получение количества таблиц очень эффективно. Поскольку я использую innodb, я просто делаю простой подсчет + выбор. В вашем случае это будет выглядеть так:
SELECT accomodation.ac_id,
accomodation.ac_status,
accomodation.ac_name,
accomodation.ac_status,
accomodation.ac_images
FROM accomodation, accomodation_category
WHERE accomodation.ac_status != 'draft'
AND accomodation.ac_category = accomodation_category.acat_id
AND accomodation_category.acat_slug != 'vendeglatohely'
AND ac_images != 'b:0;'
AND rand() <= $size * $factor / (select (SELECT count(*) FROM `accomodation`) * (SELECT count(*) FROM `accomodation_category`))
LIMIT $size
Сложная задача - определить правильную вероятность. Как вы можете видеть, следующий код фактически рассчитывает только приблизительный размер временной таблицы (на самом деле слишком грубый!): (select (SELECT count(*) FROM accomodation) * (SELECT count(*) FROM accomodation_category))
Но вы можете уточнить эту логику, чтобы приблизить размер таблицы. Обратите внимание, что лучше OVER-select, чем under-select строк. то есть, если вероятность установлена слишком низкой, вы рискуете не выбрать достаточно строк.
Это решение работает медленнее, чем решение Quassnoi, так как нам нужно пересчитать размер таблицы. Тем не менее, я считаю, что это кодирование гораздо более управляемым. Это компромисс между точность + производительность против сложность кодирования . Тем не менее, на больших столах это все еще намного быстрее, чем Order by Rand ().
Примечание. Если логика запроса позволяет, выполнить произвольный выбор как можно раньше, прежде чем выполнять какие-либо операции соединения.