SQLinfo.ru - Все о MySQL

Форум пользователей MySQL

Задавайте вопросы, мы ответим

Вы не зашли.

#1 01.05.2012 21:11:38

slipkahh
Участник
Зарегистрирован: 13.04.2012
Сообщений: 12

Выборка 10 случайных id с пробелами в ключе без RAND() и LIMIT

Добрый день, появилась проблема с БД.
Мой SELECT возвращает данные в виде

id    |    text     |   tag_name
132 | Текст132 |  Тэг1
132 | Текст132 |  Тэг76
132 | Текст132 |  Тэг43

Выглядел SELECT так:

$q=mysql_query("select id,text,tag_name from STATUS_TABLE t1 join TAG_TABLE t2 on t1.id=t2.s_id where t2.s_id='$r_a' ");
, где $r_a - случайное число от 1 до MAX(id). И так 10 раз.

Потом поймал себя на мысли, что работа с БД будет включать в себя еще и удаление некоторых id из таблицы, поэтому появляются пробелы в ключе (напр. 1 2 3 4 5 7 16 17 18 и тд).
Выборка выше может попасть в область [6-15] и вернуть пустой результат.

Рубанул с плеча, переписав так:
$q=mysql_query("select id,text,tag_name from STATUS_TABLE t1 join TAG_TABLE t2 on t1.id=t2.s_id where t2.s_id>='$r_a' LIMIT 1");

Потом понял, что вместо правильной выборки выше вернет только

id    |    text     |   tag_name
132 | Текст132 |  Тэг1

из-за LIMIT 1, а количество тэгов для данного id получать по-моему слишком накладно.

Тем таких дофига, но идеальных решений не нашел. Подскажите куда копать, спасибо!

**Совсем забыл, ORDER BY RAND() не подходит по причине толстой таблицы.

Отредактированно slipkahh (01.05.2012 21:13:30)

Неактивен

 

#2 01.05.2012 23:57:29

evgeny
Гуру
Зарегистрирован: 04.05.2009
Сообщений: 335

Re: Выборка 10 случайных id с пробелами в ключе без RAND() и LIMIT

Решением будет контролировать целостность всех номеров:
- создать новую колонку с уникальным номером допустим назовём её row_id,
- перекрутить к таблице триггер на удаление и добавление.
При добавлении, новой записи даем row_id = мах(row_id)+1
При удалении, тут посложнее : row_id удаляемой записи нужно присвоить последней записи, то есть получается самый большой row_id удалятся.

Ну а потом всё просто, с помощью php генерируем 10 чисел от 1 до мах(row_id) и делаем быстрый запрос

select id,text,tag_name from STATUS_TABLE t1 join TAG_TABLE t2 on t1.id=t2.s_id where t1.row_id in (43,32,774,242,3,12 ... )

Отредактированно evgeny (01.05.2012 23:59:11)

Неактивен

 

#3 04.05.2012 14:14:32

slipkahh
Участник
Зарегистрирован: 13.04.2012
Сообщений: 12

Re: Выборка 10 случайных id с пробелами в ключе без RAND() и LIMIT

Евгений, спасибо большое за ответ!
Смотрите какой вариант еще появился: возврат прямо-таки 10 чисел не обязателен, можно и +-3.
Делаю так: генерирую 10 чисел, далее вашим запросом с IN ( , , ... , ) выдергиваю записи, если в IN ( ... ) будет находится сгенерированый несуществующий ID, то mysql вернет не empty string, а просто пропустит этот id и вернет вместо 10 строк - девять.
Поэтому на прерывания в id можно закрыть глаза. Я прав?

Спасибо за внимание!

Неактивен

 

#4 04.05.2012 16:16:44

vasya
Архат
MySQL Authorized Developer
Откуда: Орел
Зарегистрирован: 07.03.2007
Сообщений: 5842

Re: Выборка 10 случайных id с пробелами в ключе без RAND() и LIMIT

Посмотрите ещё FAQ №9

Неактивен

 

#5 04.05.2012 17:50:41

slipkahh
Участник
Зарегистрирован: 13.04.2012
Сообщений: 12

Re: Выборка 10 случайных id с пробелами в ключе без RAND() и LIMIT

Всё попробовал, пока вроде неплохо работает.
Спасибо за FAQ, интересно!
Еще напомните пож, запрос SELECT  .. WHERE id IN ( .. , .. , .. ) ORDER BY id не приведет случайно к фулскану? Что отработает первым WHERE или ORDER BY?

Неактивен

 

#6 04.05.2012 18:02:53

vasya
Архат
MySQL Authorized Developer
Откуда: Орел
Зарегистрирован: 07.03.2007
Сообщений: 5842

Re: Выборка 10 случайных id с пробелами в ключе без RAND() и LIMIT

зависит от наличия индексов
сначала where

Неактивен

 

#7 05.05.2012 10:35:04

evgeny
Гуру
Зарегистрирован: 04.05.2009
Сообщений: 335

Re: Выборка 10 случайных id с пробелами в ключе без RAND() и LIMIT

slipkahh написал:

Всё попробовал, пока вроде неплохо работает.
Спасибо за FAQ, интересно!
Еще напомните пож, запрос SELECT  .. WHERE id IN ( .. , .. , .. ) ORDER BY id не приведет случайно к фулскану? Что отработает первым WHERE или ORDER BY?

Так что вы конкретно попробовали ?

slipkahh написал:

Смотрите какой вариант еще появился: возврат прямо-таки 10 чисел не обязателен, можно и +-3.
... а просто пропустит этот id и вернет вместо 10 строк - девять.

Так сколько конкретно вам случайных чисел надо получить 9 или 10 ? :-)

FAQ №9
Действительно более простое решение.
Опять же если вам надо вынуть не одно случайное число а 10, то вам придётся, доработать тот вариант.

Неактивен

 

#8 05.05.2012 15:00:16

slipkahh
Участник
Зарегистрирован: 13.04.2012
Сообщений: 12

Re: Выборка 10 случайных id с пробелами в ключе без RAND() и LIMIT

evgeny, я запятую забыл. Это было "всё, попробовал" и относилось к посту #3.
Сейчас работает так: http://clip2net.com/s/1SSbI (блок с пхп инсайд)
Чем больше $max, тем больше вероятность, что вернет именно 12 записей. 12 записей нужны, чтобы не грузить сервер каждым запросом текста.

С удовольствием выслушаю комментарии по моему коду smile

@all Вы отлично консультируете! Спасибо еще раз.
Вопрос еще небольшой появился: как силами mysql выдернуть из базы тэги, содержащие подстроку, присланную post-ом.
Т.е. пример: в search-field вводится например "про", отправляется в .php скрипт, далее мне нужно сконфигурировать запрос, который выдернет все тэги, содержащие "про". Выдача в виде "проекты","прогнозы","гипротранс".
Наверное и сам бы разобрался какие функции использовать, но ваш совет бесценен в этом плане! smile

Неактивен

 

#9 05.05.2012 16:10:46

evgeny
Гуру
Зарегистрирован: 04.05.2009
Сообщений: 335

Re: Выборка 10 случайных id с пробелами в ключе без RAND() и LIMIT

slipkahh написал:

evgeny, я запятую забыл. Это было "всё, попробовал" и относилось к посту #3.
Сейчас работает так: http://clip2net.com/s/1SSbI (блок с пхп инсайд)
Чем больше $max, тем больше вероятность, что вернет именно 12 записей. 12 записей нужны, чтобы не грузить сервер каждым запросом текста.

С удовольствием выслушаю комментарии по моему коду smile

Я и vasya предложили вам 2 точно работающих варианта.
Вы сделали мини кустарное подобие :-) При большом количестве удалённых строк оно будет фальшивить.
Если не хотите доделать до конца по FAQ №9,
чтоб сократить вероятность неудачных вариантов, добавите не 12 а допустим 20 id, и ограничите вывод в запросе с LIMIT 10; 

slipkahh написал:

Вопрос еще небольшой появился: как силами mysql выдернуть из базы тэги, содержащие подстроку, присланную post-ом.
Т.е. пример: в search-field вводится например "про", отправляется в .php скрипт, далее мне нужно сконфигурировать запрос, который выдернет все тэги, содержащие "про". Выдача в виде "проекты","прогнозы","гипротранс".
Наверное и сам бы разобрался какие функции использовать, но ваш совет бесценен в этом плане! smile

Функции сравнения строк
Полнотекстовый поиск в MySQL

Неактивен

 

#10 05.05.2012 19:49:26

LazY
_cмельчак
MySQL Authorized Developer and DBA
Зарегистрирован: 02.04.2007
Сообщений: 849

Re: Выборка 10 случайных id с пробелами в ключе без RAND() и LIMIT

ORDER BY RAND() не подходит по причине толстой таблицы.

А насколько быстро работает, если выбирать только id?

SELECT id
FROM ...
ORDER BY RAND()

Неактивен

 

#11 05.05.2012 21:20:26

slipkahh
Участник
Зарегистрирован: 13.04.2012
Сообщений: 12

Re: Выборка 10 случайных id с пробелами в ключе без RAND() и LIMIT

LazY, по чесноку не знаю, начитался что ORDER BY RAND() загоняет всё во временную таблицу, разве нет?
В любом случае думается мне добровольно я уже не вернусь к этом вопросу, в скором времени допарсю базу до запланированных размеров. Если что-то интересное будет - поделюсь обязательно.

За ссылки спасибо, сделал слету так: SELECT tag_name FROM TAG_TABLE WHERE tag_name like '%Тэг%'

PS никто не сталкивался? http://clip2net.com/s/1SXZ7 Через navicat SELECT выводит как надо, а функция пхп упорно возвращает 0 строк и пустую выборку.

Отредактированно slipkahh (05.05.2012 22:20:20)

Неактивен

 

#12 05.05.2012 22:31:13

evgeny
Гуру
Зарегистрирован: 04.05.2009
Сообщений: 335

Re: Выборка 10 случайных id с пробелами в ключе без RAND() и LIMIT

slipkahh написал:

PS никто не сталкивался? http://clip2net.com/s/1SXZ7 Через navicat SELECT выводит как надо, а функция пхп упорно возвращает 0 строк и пустую выборку.

Разные кодировки в php и в mysql, попробуйте слово на английском для проверки.

Неактивен

 

#13 06.05.2012 02:55:28

slipkahh
Участник
Зарегистрирован: 13.04.2012
Сообщений: 12

Re: Выборка 10 случайных id с пробелами в ключе без RAND() и LIMIT

Да, конечно, не заметил, что файл в ansi. Благодарю!

Неактивен

 

#14 07.05.2012 04:33:20

LazY
_cмельчак
MySQL Authorized Developer and DBA
Зарегистрирован: 02.04.2007
Сообщений: 849

Re: Выборка 10 случайных id с пробелами в ключе без RAND() и LIMIT

начитался что ORDER BY RAND() загоняет всё во временную таблицу

Так и есть.
SELECT id FROM t.. ORDER BY RAND() LIMIT 10 - самое простое решение. Насколько оно применимо, определяется размерами таблицы в конкретной ситуации.
Например, на не особо мощном домашнем компьютере такой запрос для таблицы в сто тысяч строк выполняется менее одной десятой секунды. Для таблицы в полтора миллиона записей - уже полторы секунды.
Если, например, у вас 100k записей и 0.1 с вам подходит - можно использовать это простое решение.

Неактивен

 

#15 07.05.2012 14:59:31

slipkahh
Участник
Зарегистрирован: 13.04.2012
Сообщений: 12

Re: Выборка 10 случайных id с пробелами в ключе без RAND() и LIMIT

LazY, вариант с IN ( .. , .. , .. ) отрабатывает сейчас за 0.04с , так что думаю вне конкуренции.
Кстати никогда не сталкивался с паданием сервера от нагрузки. Если запрос допустим обрабатывается 0.1с и в секунду приходит более 10 запросов, что происходит с остальными запросами? Просто выкидываются из очереди?

Неактивен

 

#16 07.05.2012 16:10:40

LazY
_cмельчак
MySQL Authorized Developer and DBA
Зарегистрирован: 02.04.2007
Сообщений: 849

Re: Выборка 10 случайных id с пробелами в ключе без RAND() и LIMIT

На перегруженном сервере запросы встают в очередь, соединение, через которое послан запрос, остается открытым, пока он не завершится, либо отваливается по тайм-ауту.
Количество одновременных соединений ограничено, и когда число единовременно открытых соединений сравнивается с ограничением, "свободных мест" для новых соединений не остается, и следующему клиенту сервер БД просто отвечает отказом и никакие запросы даже не начинают выполняться.

Неактивен

 

#17 11.05.2012 19:34:43

slipkahh
Участник
Зарегистрирован: 13.04.2012
Сообщений: 12

Re: Выборка 10 случайных id с пробелами в ключе без RAND() и LIMIT

Еще вопрос появился. Решил привести табличку в порядок, наткнулся на непонятное что-то.
Запрос:

SELECT COUNT(*) FROM STATUS_TABLE t1 JOIN TAG_TABLE t2 ON t2.s_id=t1.id WHERE LENGTH(t1.text)>204
выдает 26038 строк.
Удаляю их запросом
DELETE FROM t1,t2 USING STATUS_TABLE t1 JOIN TAG_TABLE t2 ON t2.s_id=t1.id WHERE LENGTH(t1.text)>204

Выдает: affected rows: 42350

Откуда еще 16тыс. строк и где я не прав?
После последнего запроса первый запрос выдает 0, как и должно быть.
Спасибо за внимание!

ПС. под каждый такой вопрос может лучше тему отдельную заводить или не стоит?

**** как всегда под вечер туплю. Очевидно, что из разных таблиц строки удаляются, в сумме как раз 42тыс дают. Извините.

Отредактированно slipkahh (12.05.2012 00:23:34)

Неактивен

 

Board footer

Работает на PunBB
© Copyright 2002–2008 Rickard Andersson