Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
Топик располагается на нескольких страницах: [1] 2   вперед  Ctrl      все
 Получить случайное значение из большой таблицы  [new]
Felas
Member

Откуда: Санкт-Петербург
Сообщений: 16
Доброго времени суток.

Есть таблица содержит примерно 16кк записей, есть задача время от времени выдергивать из нее случайные записи по определенным критериям (WHERE с 4 условиями). Использовать
order by newid()
религия не позволяет в силу того, что запрос отрабатывает крайне долго.

ЗЫ Если нужны еще какие данные все напишу ))

Заранее спасибо.
30 май 13, 16:19    [14371299]     Ответить | Цитировать Сообщить модератору
 Re: Получить случайное значение из большой таблицы  [new]
Паганель
Member

Откуда: Винница
Сообщений: 22550
Felas
16кк записей
миллионов чтоли?

а после наложения Where сколько остается?
30 май 13, 16:23    [14371333]     Ответить | Цитировать Сообщить модератору
 Re: Получить случайное значение из большой таблицы  [new]
Felas
Member

Откуда: Санкт-Петербург
Сообщений: 16
Паганель
Felas
16кк записей
миллионов чтоли?

а после наложения Where сколько остается?


Да миллионов.

Запрос в чистом виде выглядит примерно так:
select top 1 * from table 
where param1 = X 
and param2 = Y
and param3 = 'Z'
and param4 in (1,2,3,4...n)
.
Задача сделать так чтобы полученное значение всегда было случайным.
30 май 13, 16:28    [14371371]     Ответить | Цитировать Сообщить модератору
 Re: Получить случайное значение из большой таблицы  [new]
Glory
Member

Откуда:
Сообщений: 104751
Felas
Задача сделать так чтобы полученное значение всегда было случайным.

Сколько записей то отбирается фильтром ?
30 май 13, 16:29    [14371387]     Ответить | Цитировать Сообщить модератору
 Re: Получить случайное значение из большой таблицы  [new]
iap
Member

Откуда: Москва
Сообщений: 47198
Felas,

и сколько же случайных записей надо выдернуть время от времени?
30 май 13, 16:31    [14371398]     Ответить | Цитировать Сообщить модератору
 Re: Получить случайное значение из большой таблицы  [new]
Felas
Member

Откуда: Санкт-Петербург
Сообщений: 16
Glory
Felas
Задача сделать так чтобы полученное значение всегда было случайным.

Сколько записей то отбирается фильтром ?


Если не указывать топ 1 то значение всегда разное от 0 до 10000000
30 май 13, 16:31    [14371403]     Ответить | Цитировать Сообщить модератору
 Re: Получить случайное значение из большой таблицы  [new]
Felas
Member

Откуда: Санкт-Петербург
Сообщений: 16
iap
Felas,

и сколько же случайных записей надо выдернуть время от времени?


Всего 1, но именно случайную, чтобы если запрос выполнялся 2 раза подряд с одними и тем же входными параметрами он возвращал разные записи
30 май 13, 16:32    [14371408]     Ответить | Цитировать Сообщить модератору
 Re: Получить случайное значение из большой таблицы  [new]
iap
Member

Откуда: Москва
Сообщений: 47198
Надо сгенерировать случайное id и выбрать из таблицы
запись с этим id (или из случайно вычисленного диапазона).
Потому что зачем же для каждой записи вызывать NEWID(), если понадобится только одна?
30 май 13, 16:35    [14371429]     Ответить | Цитировать Сообщить модератору
 Re: Получить случайное значение из большой таблицы  [new]
Паганель
Member

Откуда: Винница
Сообщений: 22550
Felas
Glory
пропущено...

Сколько записей то отбирается фильтром ?


Если не указывать топ 1 то значение всегда разное от 0 до 10000000
я так понял зависит от списка param4

а перечисленные param4 обязательно будут в БД?
(мало ли, может они перед этим получены другим select-ом)

если так, то не убрать ли из запроса все кроме одного случайного из них
30 май 13, 16:40    [14371459]     Ответить | Цитировать Сообщить модератору
 Re: Получить случайное значение из большой таблицы  [new]
Felas
Member

Откуда: Санкт-Петербург
Сообщений: 16
Паганель
Felas
пропущено...


Если не указывать топ 1 то значение всегда разное от 0 до 10000000
я так понял зависит от списка param4

а перечисленные param4 обязательно будут в БД?
(мало ли, может они перед этим получены другим select-ом)

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


Все параметры обязательно будут в БД, записей с такими параметрами может быть много очень много, нужна всего 1 и случайная, потому что скрипт запускается примерно 80-100 раз подряд (ну вот такая архитектура приложения (( ) и каждый раз должно быть новое значение, хотя входящие параметры одинаковы
30 май 13, 16:49    [14371507]     Ответить | Цитировать Сообщить модератору
 Re: Получить случайное значение из большой таблицы  [new]
Felas
Member

Откуда: Санкт-Петербург
Сообщений: 16
iap
Надо сгенерировать случайное id и выбрать из таблицы
запись с этим id (или из случайно вычисленного диапазона).
Потому что зачем же для каждой записи вызывать NEWID(), если понадобится только одна?


Можно подробнее, хотя бы примерный запрос )
30 май 13, 16:49    [14371510]     Ответить | Цитировать Сообщить модератору
 Re: Получить случайное значение из большой таблицы  [new]
ambarka_max
Member

Откуда: Россия
Сообщений: 517
Запрос к таблице формируется через хранимую процедуру или прямо из приложения голый запрос посылается?
30 май 13, 16:55    [14371544]     Ответить | Цитировать Сообщить модератору
 Re: Получить случайное значение из большой таблицы  [new]
Felas
Member

Откуда: Санкт-Петербург
Сообщений: 16
ambarka_max
Запрос к таблице формируется через хранимую процедуру или прямо из приложения голый запрос посылается?


Пока никак не формируется, потому что собственно запроса то нет еще, реализовать можно и то и то, главное сам запрос сделать )
30 май 13, 16:57    [14371557]     Ответить | Цитировать Сообщить модератору
 Re: Получить случайное значение из большой таблицы  [new]
Glory
Member

Откуда:
Сообщений: 104751
Felas
Всего 1, но именно случайную, чтобы если запрос выполнялся 2 раза подряд с одними и тем же входными параметрами он возвращал разные записи

Т.е. вы хотите из 10 миллионной выборки каждый раз выбирать одну действительно случайную запись ?
30 май 13, 16:59    [14371569]     Ответить | Цитировать Сообщить модератору
 Re: Получить случайное значение из большой таблицы  [new]
Felas
Member

Откуда: Санкт-Петербург
Сообщений: 16
Glory
Felas
Всего 1, но именно случайную, чтобы если запрос выполнялся 2 раза подряд с одними и тем же входными параметрами он возвращал разные записи

Т.е. вы хотите из 10 миллионной выборки каждый раз выбирать одну действительно случайную запись ?


Да
30 май 13, 17:00    [14371574]     Ответить | Цитировать Сообщить модератору
 Re: Получить случайное значение из большой таблицы  [new]
ambarka_max
Member

Откуда: Россия
Сообщений: 517
Felas
ambarka_max
Запрос к таблице формируется через хранимую процедуру или прямо из приложения голый запрос посылается?


Пока никак не формируется, потому что собственно запроса то нет еще, реализовать можно и то и то, главное сам запрос сделать )

Тогда делаете процедуру. По 4-ем параметрам отбираете ID-шники (например во времянку) и order by newid() возвращаете сразу TOP 80 (сразу все что нужны)
Не?
30 май 13, 17:00    [14371575]     Ответить | Цитировать Сообщить модератору
 Re: Получить случайное значение из большой таблицы  [new]
Felas
Member

Откуда: Санкт-Петербург
Сообщений: 16
ambarka_max
Felas
пропущено...


Пока никак не формируется, потому что собственно запроса то нет еще, реализовать можно и то и то, главное сам запрос сделать )

Тогда делаете процедуру. По 4-ем параметрам отбираете ID-шники (например во времянку) и order by newid() возвращаете сразу TOP 80 (сразу все что нужны)
Не?


Делать временную думал, но решил спросить может есть какой другой интересный способ. К сожалению архитектура приложения такова, что она не хранит данные полученные от первого запроса, приложение их обрабатывает и сжигает (понимаю, что не самое лучшее решение, но сделать ничего нельзя с этим). Поэтому запросы запускаются один за одним нужное количество раз.
30 май 13, 17:04    [14371588]     Ответить | Цитировать Сообщить модератору
 Re: Получить случайное значение из большой таблицы  [new]
ambarka_max
Member

Откуда: Россия
Сообщений: 517
Если не подходит, то можно еще реализовать очередь заранее случайных идешников для каждой комбинации отбора. Но тут будет конкуренция поэтому придется повышать уровень в момент чтения очереди.
30 май 13, 17:04    [14371591]     Ответить | Цитировать Сообщить модератору
 Re: Получить случайное значение из большой таблицы  [new]
Гость333
Member

Откуда:
Сообщений: 3683
Felas
приложение их обрабатывает и сжигает

Действию "сжигает" соответствует какая-то SQL-команда?
30 май 13, 17:11    [14371635]     Ответить | Цитировать Сообщить модератору
 Re: Получить случайное значение из большой таблицы  [new]
Felas
Member

Откуда: Санкт-Петербург
Сообщений: 16
Гость333
Felas
приложение их обрабатывает и сжигает

Действию "сжигает" соответствует какая-то SQL-команда?


"Сжигает" их внутри себя, причем тут sql-команда?
30 май 13, 17:13    [14371644]     Ответить | Цитировать Сообщить модератору
 Re: Получить случайное значение из большой таблицы  [new]
iap
Member

Откуда: Москва
Сообщений: 47198
Можно же сгенерировать случайный порядковый номер
в порядке возрастания ID от 1 до COUNT(*)?

После этого выбрать эту запись, используя ROW_NUMBER(), например?

Если ID последовательно возрастает без пропусков,
то вообще всё идеально будет и без ROW_NUMBER().
30 май 13, 17:19    [14371684]     Ответить | Цитировать Сообщить модератору
 Re: Получить случайное значение из большой таблицы  [new]
Гость333
Member

Откуда:
Сообщений: 3683
Felas
Гость333
пропущено...

Действию "сжигает" соответствует какая-то SQL-команда?


"Сжигает" их внутри себя, причем тут sql-команда?

А обрабатывает как?
Я это к чему — если "случайной записью" при двух последовательных запусках запроса окажется одна и та же запись, как поведёт себя приложение?
30 май 13, 17:21    [14371701]     Ответить | Цитировать Сообщить модератору
 Re: Получить случайное значение из большой таблицы  [new]
Glory
Member

Откуда:
Сообщений: 104751
Felas
Делать временную думал, но решил спросить может есть какой другой интересный способ. К сожалению архитектура приложения такова, что она не хранит данные полученные от первого запроса, приложение их обрабатывает и сжигает (понимаю, что не самое лучшее решение, но сделать ничего нельзя с этим). Поэтому запросы запускаются один за одним нужное количество раз.

По-моему надо думать над ограничением размера выборки.
Например, выбирать не больше 100 записей. Из которых потом уже возвращать одну случайную.
30 май 13, 17:22    [14371708]     Ответить | Цитировать Сообщить модератору
 Re: Получить случайное значение из большой таблицы  [new]
ambarka_max
Member

Откуда: Россия
Сообщений: 517
Может быть не понятно выразился:
Cоздаете доп таблицу ИдентификаторыОтбора где хранится идентификатор отбора (можно хотя бы в виде текста хранить выражение WHERE).

1.Для каждого уникального WHERE отбираем К записей и помещаем их в таблицу ОчередьНеИспользованных (ИдентификаторОтбора, Использовано NOT NULL, ссылка на ID). Тут можно подумать над сортировкой перед вставкой, дабы выбрать "случайные" K записей

2.Далее основной алгоритм работает так: по выражению WHERE определяем идентификатор отбора и смотрим скока там в ОчередиНеИспользованных. Если что-то есть, читаем, при чтении TOP 1 ... WHERE ИдентификаторОтбора = X AND Использовано = 0 повышаем блокировку до например XLOCK и тут же UPDATE Использовано = 1.
Если в очереди нет ничего для нашего WHERE - идем на шаг 1.

3.Возвращаем полученный идешник
30 май 13, 17:22    [14371709]     Ответить | Цитировать Сообщить модератору
 Re: Получить случайное значение из большой таблицы  [new]
Felas
Member

Откуда: Санкт-Петербург
Сообщений: 16
iap
Можно же сгенерировать случайный порядковый номер
в порядке возрастания ID от 1 до COUNT(*)?

После этого выбрать эту запись, используя ROW_NUMBER(), например?

Если ID последовательно возрастает без пропусков,
то вообще всё идеально будет и без ROW_NUMBER().


Можно хотя бы примерный скрипт, не являюсь гуру SQL
30 май 13, 17:23    [14371717]     Ответить | Цитировать Сообщить модератору
Топик располагается на нескольких страницах: [1] 2   вперед  Ctrl      все
Все форумы / Microsoft SQL Server Ответить