Задавайте вопросы, мы ответим
Вы не зашли.
Опять я и с новой темой.
Имеем таблицы t1 и t2
из одной таблицы выбираем случайные значения вот таким образом:
Отредактированно Doxtor (24.08.2009 18:09:52)
Неактивен
Что-то типа этого???
Неактивен
Честно говоря, не понял вопроса. Что значит — «одновременно из двух таблиц»?
У них одинаковые структуры? Почему тогда две таблицы?
Неактивен
Ахаа, пока писал — вы дописали... ну, именно так, только еще скобки поставить
(SELECT ... UNION SELECT ... ) LIMIT 10;
Только тормозить будет совершенно бессовестно.
Обычно делают SELECT ID ORDER BY RAND() LIMIT 10 и к нему потом прицепляют
сбоку основные данные. На не очень длинных таблицах работает.
И вопрос «почему тогда две таблицы» таки в силе
Неактивен
1. Со скобками не работает.
Пишет: #1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'UNION
2. SELECT ID ORDER BY RAND() LIMIT 10 медленнее же работает вроде. Поменьшей мере без UNION
3. В разных таблицах лежат разные типы материала и поэтому так проще администрировать.
Неактивен
1. Да, мне казалось, что он понимает LIMIT после скобок — ан нет, прийдется дописать до
подзапроса.
2. Зато Ваш вариант выбирает одно случайное значение, и 10 ссылок после него — кажется,
это не совсем случайно уже
3. Мне казалось, что добавить поле проще — ну, кому как нравится. UNION всегда работают
хуже, чем дополнительное поле.
--
А вообще, это всегда сложная тема. Обычно если таблицы небольшие, то ORDER BY RAND()
от ID работает достаточно быстро. Если таблицы большие, то как правило достаточно взять
последние 1000 записей и выбирать RAND среди их ID.
Неактивен
Да похоже придётся делать через SELECT ID ORDER BY RAND()
Но как выбрать из двух таблиц не пойму никак.
Помогите составить запрос, позалуйста.
Отредактированно Doxtor (24.08.2009 19:14:44)
Неактивен
Никак, у Вас же ID пересекаются в разных табличках. Нужно или принять
условие «пять из этой таблички и пять из этой», или рандомизировать вместе
с данными
Неактивен
рандомизировать вместе с данными???
Это как?
Может я не совсем правильно выразился: нужно просто взять все поля из t1 и все поля из t2, их перемешать и вывести с LIMIT N
Могу сделать разные id в разных таблицах
Отредактированно Doxtor (24.08.2009 19:25:17)
Неактивен
Пусть у Вас есть таблица из всего двух столбцов — номер и данные (id + data).
id занимает 4 байта, ибо это число. data занимает много больше памяти (например,
пусть это будет 100 байт — не такое большое значение). А теперь внимание — строк
1000 штук. Для того чтобы выбрать 10 штук id методом ORDER BY RAND(), нужно
отсортировать 4 килобайта данных в памяти. Для того, чтобы «взять все поля из»
и выбрать те же 10 строк, нужно отсортировать в памяти 100 килобайт данных!
Может, разница кажется и не такой большой, но на большом количестве запросов
это сильно сказывается. А если учесть, что реальные данные обычно более 100
символов в данных, если сортировать «в лоб», то Вы начинаете сортировать мегабайты
информации для того, чтобы получить выжимку из 200-300 байт.
Неактивен
Обьединение таблиц отменяется.
Будем выбирать из одной.
По поводу вашего комментария...
Да...это понятно.
Но я ведь всё равно должен выбрать всё из таблицы SELECT * FROM table ORDER BY rand()
Т.к. выводить я хочу именно data, а не id
Или я не прав?
Неактивен
Вам нужно получить 10 значений data, но при этом не нужно сортировать их — это
будет неэкономно по ресурсам. Гораздо эффективнее отсортировать id, выбрать
оттуда 10 штук, а потом по этим id найти данные. Это тот случай, когда самообъединение
таблицы увеличивает производительность запроса.
SELECT t1.data
FROM tablename t1
JOIN (SELECT id FROM tablename ORDER BY RAND() LIMIT 10) t2 USING (id);
Неактивен
Ничего не имею против экономии ресурсов.
Если я правильно вас понял, то в этом случае необходимо иметь две идентичные таблицы?!
Или как долзны выглядеть эти таблицы?
Неактивен
Нет, одной таблицы хватит. Самообъединение — на то и само, чтобы объединять
одну таблицу с самой собой (см пример выше).
Неактивен
Огромное спасибо разобрался:
имеем таблицу t1 с колонками id и data
запрос выглядит вот так
Отредактированно Doxtor (26.08.2009 15:45:43)
Неактивен
Хм, так быть не должно ключик на id есть? Вам и правда нужно 200 значений?
Неактивен
Первичный ключ есть.
200 - для примера.
Неактивен
А explain от этого запроса покажите, пожалуйста
Неактивен
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 200
1 PRIMARY g_rattan eq_ref PRIMARY PRIMARY 4 t2.id 1
2 DERIVED g_rattan index NULL PRIMARY 4 NULL 330 Using index; Using temporary; Using filesort
Отредактированно Doxtor (26.08.2009 19:12:39)
Неактивен
Кошмар и ужас! Выбирать 200 строк из 300 рандомно — по индексу дольше, да
Неактивен
Ну, я же для примера.
И в этом конкретном случае рэндом необходим.
Если ничего нельзя сделать, то ничего, результатом я всёравно доволен.
Большое спасибо за помощь.
Отредактированно Doxtor (27.08.2009 11:57:02)
Неактивен
Эм, объясню, что мне не нравится в числе 200.
Данные из таблиц забираются путем чтения их с диска. Как известно, читать с диска
последовательно — быстрее, чем читать из разных частей диска (передвижение головки
по диску — seek — это дорогая операция). Поэтому в данном случае оказывается, что
вытащить все данные с диска последовательно и отсортировать в памяти — быстрее, чем
вытащить данные точечно, уже сортированные (но с помощью seekов).
Обычная ситуация — вытащить случайные 5 строк из тысячи, например. Безусловно,
вытащить 5 случайных строк куда быстрее, чем прочитать и отсортировать 1000. В Вашем
же случае, Вы достаете 200 записей из 300.
Это я все к тому, что когда табличка разрастется, способ начнет давать свои преимущества.
Если же Вы всегда планируете доставать большую часть таблицы, то нужно действительно
доставать все, и со всеми данными уже играть в памяти.
Неактивен
Ещё раз спасибо за компетентный ответ. Буду иметь в виду
Пока разница в скорости минимальная, но буду следить.
Неактивен