PDA

Просмотр полной версии : [Вопрос] SQL запрос



M1RoN
08.09.2017, 22:19
Приветствую всех
Такой вопрос возник
можно ли создать такой sql запрос, чтобы заполнить пустую таблицу рандомными номерами (около 1000000 номеров) без повторений?
Номера следующего вида:

АXXXAA
То бишь чтобы были стандартные российские номера.

Alpano
08.09.2017, 22:51
Одним запросом, не думаю.
Продумай алгоритм, который будет поочередно генерировать номера и отправлять запросы в БД.
Сначала А---АА , + 999 номеров,
потом А---АВ и т.д.

DeimoS
08.09.2017, 23:55
Как я понимаю, это будут автомобильные номера, что ты хочешь использовать в системе авто. Но для чего такие извращения? Не проще ли составить простой алгоритм, который будет на ходу генерировать рандмный номер? После просто записывай эти номера в базу, а перед этим смотри, есть ли уже такие номера и если есть - генерируй по новой. Выйдет гораздо надёжнее и логичнее

123
09.09.2017, 05:44
Как я понимаю, это будут автомобильные номера, что ты хочешь использовать в системе авто. Но для чего такие извращения? Не проще ли составить простой алгоритм, который будет на ходу генерировать рандмный номер? После просто записывай эти номера в базу, а перед этим смотри, есть ли уже такие номера и если есть - генерируй по новой. Выйдет гораздо надёжнее и логичнее
Поздравляю, этим самым ты успешно убил свой сервер (он просто завис). Почему? Все просто - например, как сейчас реализована подобная система в большинстве модов:

Рандом
Запрос в базу, узнает не совпадает ли номер с уже существующим
Если совпадает - повторить

Тем самым, если у тебя много запискй (например 1000000) угадай, примерно сколько запросов в базу уйдет? Это приведет к рекурсии ( наверно говорить про один поток и что зависнит весь сервер смысла нет).

По поводу тему, попробуй вот это

CREATE TABLE IF NOT EXISTS `CarPlate` (
`ID` int(11) NOT NULL AUTO_INCREMENT,
`Number` varchar(5) NOT NULL,
`Vehicle` int(11) NOT NULL DEFAULT '-1',
PRIMARY KEY (`ID`),
UNIQUE KEY `Number` (`Number`,`Vehicle`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
DELIMITER //
CREATE PROCEDURE lol()
BEGIN
set @chars = 'ABCEHKMOPTXY';
set @i = 999;
WHILE @i > 0 DO
set @c1=1;
WHILE 12 >= @c1 DO
set @c2=1;
WHILE 12 >= @c2 DO
insert into `CarPlate` set `Number` = lpad(lpad(lpad(@i,3,'000'),4,substring(@chars,@c2,1)),5,substring(@chars,@c1,1));
set @c2=@c2+1;
END WHILE;
set @c1=@c1+1;
END WHILE;
set @i=@i-1;
END WHILE;
END; //
call lol()

DeimoS
09.09.2017, 13:06
Поздравляю, этим самым ты успешно убил свой сервер (он просто завис). Почему? Все просто - например, как сейчас реализована подобная система в большинстве модов:

Рандом
Запрос в базу, узнает не совпадает ли номер с уже существующим
Если совпадает - повторить

Тем самым, если у тебя много запискй (например 1000000) угадай, примерно сколько запросов в базу уйдет? Это приведет к рекурсии ( наверно говорить про один поток и что зависнит весь сервер смысла нет).


А теперь попробуй погуглить пропускную способность MySQL сервера ;) Для него твои 1.000.000 простых запросов будут плёвым делом, даже если ты их за секунду все отправишь. Он и миллион сложных запросов прожевать сможет спокойно, если и таблицы, к которым идёт обращение, и сами запросы составлены как подобает. А вот обращаться к подобной таблице с миллионом записей и без адекватных индексов постоянно будет гораздо затратнее (особенно если автор решит прямо из неё выгружать номера при запуске сервера).

Да и кто сказал, что нужно просто рандомить? -_- Для кого я уточнил в своём сообщении, что нужно составить АЛГОРИТМ? Достаточно просто, например, сначала рандомно формировать номера, начинающиеся с A (все остальные значения уже рандомные) и если с базы данных пришло, допустим, 30 положительных ответов (номера уже существуют), менять начальную букву на B. При желании, можно придумать алгоритм, в котором вообще генерироваться будут только цифры, а буквы уже подбирать по другому алгоритму (например, исходя из получившихся цифр). Или же добавить ещё подобие регионов, как это сделано на тех же Российских номерах, дабы увеличить количество возможных вариантов. Всё только от фантазии и изгиба рук зависит.

А привязывать всю систему к одной заранее заготовленной таблице - такое себе решение. Мало того, что, как я уже сказал, общение с такой таблицей далеко не самым оптимизированным путём пойдёт, так ещё и есть риск заполнения владельцами всех номеров, что там будут, если автор не будет следить за "сроком годности" информации, которая хранится у него в таблице. Вгонять себя в рамки, конечно, проще и кажется, что это оптимальнее, но в перспективе от такого подхода есть только вред, увы.

123
09.09.2017, 16:40
А теперь попробуй погуглить пропускную способность MySQL сервера ;) Для него твои 1.000.000 простых запросов будут плёвым делом, даже если ты их за секунду все отправишь. Он и миллион сложных запросов прожевать сможет спокойно, если и таблицы, к которым идёт обращение, и сами запросы составлены как подобает. А вот обращаться к подобной таблице с миллионом записей и без адекватных индексов постоянно будет гораздо затратнее (особенно если автор решит прямо из неё выгружать номера при запуске сервера).

Да и кто сказал, что нужно просто рандомить? -_- Для кого я уточнил в своём сообщении, что нужно составить АЛГОРИТМ? Достаточно просто, например, сначала рандомно формировать номера, начинающиеся с A (все остальные значения уже рандомные) и если с базы данных пришло, допустим, 30 положительных ответов (номера уже существуют), менять начальную букву на B. При желании, можно придумать алгоритм, в котором вообще генерироваться будут только цифры, а буквы уже подбирать по другому алгоритму (например, исходя из получившихся цифр). Или же добавить ещё подобие регионов, как это сделано на тех же Российских номерах, дабы увеличить количество возможных вариантов. Всё только от фантазии и изгиба рук зависит.

А привязывать всю систему к одной заранее заготовленной таблице - такое себе решение. Мало того, что, как я уже сказал, общение с такой таблицей далеко не самым оптимизированным путём пойдёт, так ещё и есть риск заполнения владельцами всех номеров, что там будут, если автор не будет следить за "сроком годности" информации, которая хранится у него в таблице. Вгонять себя в рамки, конечно, проще и кажется, что это оптимальнее, но в перспективе от такого подхода есть только вред, увы.

Я почему-то думал, что ты грамотный человек и признаешь свою ошибку выше, но увы... Ты как идиот, неся полную чушь пытаешь доказать свою точку зрения(((( это очень печально.

Или ты просто не понимаешь, о чем говоришь? Окей. Загуглил - пропускная способность MySQL сервера по операциям чтения/записи 5 - 10 к в секунду. Да и причем тут MySQL сервер, когда первое, что отправляет эти запросы твоя AMX машина, которая, соотвественно и завистнит на долгое время, пока все запросы отправятся (если те самые 10 миллионов запросов вообще отправятся, т.к. далеко не всегда, придется обрабатывать только один номер, в нормальных условиях для нескольких машин сразу придется это делать).

Окей, возьмем случай, что нужно найти один свободный номер (хотя надеюсь, что ты понимаешь, что может быть потребуется найти и 10 номеров за минуту): Ты действительно считаешь, что 1 миллионов запросов (хотя может быть и больше, поскольку рандом шттука такая, может выдавать одно и тоже по несколько раз, если конечно, не писать какие-то специальные алгоритмы под это дело) быстрее чем один 1 запрос, вида:


SELECT `ID`, `Number` FROM `phones` WHERE `Player` = -1 ORDER BY RAND() LIMIT 1

Ты безумен, не иначе.

По поводу идексов - посмотри мой пример, таблица готова, индексы настроены (осталось только выполнить запрос, и все будет готово к работе). И что значит следить за "сроком годности"? Точно также, как и без этой таблицы. Все делается прям очень легко:

UPDATE `phones` SET `Player` = '-1' WHERE `ID` = (SELECT a.`ID` FROM (SELECT `ID` FROM `phones` WHERE `Number` = '%s' LIMIT 1) as `a`) LIMIT 1 - забираем у игрока номер и очищаем в таблице аккаунтов его переменную.

Если и сейчас ты будет утверждать, что миллионов запросов быстрее одного, то пожалуй, мне нечего тебе сказать, пускай это дело останется на суд читателей, я привел достаточно материала и достаточно доводов (да и даже чисто логически подумать, без специальных знаний). Проводи тест и выкладывай результаты (хотя я сомневаюсь, что твой тест завершится, сервер тупо зависнит).

DeimoS
09.09.2017, 18:00
Или ты просто не понимаешь, о чем говоришь? Окей. Загуглил - пропускная способность MySQL сервера по операциям чтения/записи 5 - 10 к в секунду. Да и причем тут MySQL сервер, когда первое, что отправляет эти запросы твоя AMX машина, которая, соотвественно и завистнит на долгое время, пока все запросы отправятся (если те самые 10 миллионов запросов вообще отправятся, т.к. далеко не всегда, придется обрабатывать только один номер, в нормальных условиях для нескольких машин сразу придется это делать).

По твоей логике, amx машина должна и от вызова функции random виснуть -_-
Сервер лишь формирует запрос и отправляет его плагину. А плагин уже сам занимается общением с MySQL сервером. AMX машина вообще никак страдать не будет.


И что значит следить за "сроком годности"? Точно также, как и без этой таблицы. Все делается прям очень легко:

UPDATE `phones` SET `Player` = '-1' WHERE `ID` = (SELECT a.`ID` FROM (SELECT `ID` FROM `phones` WHERE `Number` = '%s' LIMIT 1) as `a`) LIMIT 1 - забираем у игрока номер и очищаем в таблице аккаунтов его переменную.

А теперь скажи нам в какой именно момент времени автору следует отбирать у игроков номер? И какова вероятность того, что за этот промежуток времени все номера не выкупят в конечном счёте?


Окей, возьмем случай, что нужно найти один свободный номер (хотя надеюсь, что ты понимаешь, что может быть потребуется найти и 10 номеров за минуту): Ты действительно считаешь, что 1 миллионов запросов (хотя может быть и больше, поскольку рандом шттука такая, может выдавать одно и тоже по несколько раз, если конечно, не писать какие-то специальные алгоритмы под это дело) быстрее чем один 1 запрос, вида:


SELECT `ID`, `Number` FROM `phones` WHERE `Player` = -1 ORDER BY RAND() LIMIT 1

Ты безумен, не иначе.

О каком миллионе запросов ты говоришь? -_- С чего ты взял, что речь вообще идёт тупо о рандоме? Да и каким бы не был рандом в случае единичного вызова, когда ты рандомишь 4 разных значения (3 буквы + номер в виде числа), шанс на то, что получится значение, схожее с предыдущим, ничтожно мал. А если ещё и нормальный алгоритм написать, а не надеяться сугубо на рандом, то и шанс того, что значение уже будет записано в таблице, тоже можно свести к минимуму.

На суд читателей следует вынести то, что ты как-то исковеркал мою идею реализации под свой лад и теперь пытаешься сказать, что я не прав. Почему до тебя так и не доходит, что вся моя идея заключается в том, чтоб не надеяться тупо на рандом и не помещать всю систему в какие-то непонятные и не нужные рамки, а ещё на уровне написания всей системы продумать алгоритм, который бы генерировал максимально уникальный номер? Сделать явный псевдорандом, который будет подчиняться заранее прописанным правилам. А уже результат на всякий случай перепроверять в таблице.
Если всё сделать по уму и правильно, на выходе не будет никакого миллиона запросов или зависания сервера. При этом и ограничений никаких не будет. Всего лишь нужно подключить фантазию, перебороть лень и написать что-то сложнее, чем пара запросов, тем самым обезопасив себя от проблем в будущем.

Хотя можешь и дальше задвигать про какие-то рекурсии и зависания серверов, если тебе так угодно. А я пойду дальше заниматься своими безумными делами. На этом и закончим этот бессмысленный диалог :hi:

123
10.09.2017, 03:56
По твоей логике, amx машина должна и от вызова функции random виснуть -_-
Сервер лишь формирует запрос и отправляет его плагину. А плагин уже сам занимается общением с MySQL сервером. AMX машина вообще никак страдать не будет.



А теперь скажи нам в какой именно момент времени автору следует отбирать у игроков номер? И какова вероятность того, что за этот промежуток времени все номера не выкупят в конечном счёте?



О каком миллионе запросов ты говоришь? -_- С чего ты взял, что речь вообще идёт тупо о рандоме? Да и каким бы не был рандом в случае единичного вызова, когда ты рандомишь 4 разных значения (3 буквы + номер в виде числа), шанс на то, что получится значение, схожее с предыдущим, ничтожно мал. А если ещё и нормальный алгоритм написать, а не надеяться сугубо на рандом, то и шанс того, что значение уже будет записано в таблице, тоже можно свести к минимуму.

На суд читателей следует вынести то, что ты как-то исковеркал мою идею реализации под свой лад и теперь пытаешься сказать, что я не прав. Почему до тебя так и не доходит, что вся моя идея заключается в том, чтоб не надеяться тупо на рандом и не помещать всю систему в какие-то непонятные и не нужные рамки, а ещё на уровне написания всей системы продумать алгоритм, который бы генерировал максимально уникальный номер? Сделать явный псевдорандом, который будет подчиняться заранее прописанным правилам. А уже результат на всякий случай перепроверять в таблице.
Если всё сделать по уму и правильно, на выходе не будет никакого миллиона запросов или зависания сервера. При этом и ограничений никаких не будет. Всего лишь нужно подключить фантазию, перебороть лень и написать что-то сложнее, чем пара запросов, тем самым обезопасив себя от проблем в будущем.

Хотя можешь и дальше задвигать про какие-то рекурсии и зависания серверов, если тебе так угодно. А я пойду дальше заниматься своими безумными делами. На этом и закончим этот бессмысленный диалог :hi:

Про какие рамки ты все время говоришь? Алгоритм выше генерирует все возможные значения для этих самых 6 значений. Соответственно, будет все также, как и без таблицы.

Когда следует забирать номер - это уже дело конечного разработчика системы. Наиболее очевидные - при удалении аккаунта (достаточно просто из таблицы номеров). В конечном итоге разницы между с таблицей номеров и без неё - не будет. Разве что, без зависания сервера и отправкой кучи запросов в никуда. Ах да, и самое главное - без написания каких то безумных и никому ненужных алгоритмов на генерацию нужного тебе номера.

По поводу твоего алгоритма - я вообще сути не понимаю. Допустим, можно сделать так, что бы генерируемые значения не повторялись, окей. Можно еще сделать так, что бы те номера, которые уже на сервере, не попадали в генерацию - окей. И что еще? Да ничего, в итоге мы получаем непонятный код, который в + к запросам будет тратить драгоценное процессорное время. А запросов то в конечном итоге меньше не стало..

Единственный способ, сделать без таблицы адекватный вариант, это сделать все по порядку. Без таблицы, без всяких заморочек, в виде алгоритма и т.д. Но как это без рандома? Кто будет играть на таком сервере?

$continue$
10.09.2017, 04:19
Так плагин давно научился в многопоточности. Раньше сервера повисали из-а однопоточности, но щас таких проблем не наблюдается.

И если на то пошло: VK (наверняка используют MySQL, но это не точно) - запросов там гораздо больше, чем в SA-MP. Тогда вопрос: почему там овер999 запросов не лагают, а у Вас в SA-MP'e они лагают (не надо мне рассказывать про однопоточность AMX, ибо все что делается в amx: форматируется строка [запрос] и передается в плагин, где запускаются отдельные от сервера потоки для запросов). Так смешно наблюдать как люди боятся выполнять много запросов, но никогда не задумывались, что MySQL в SA-MP'e это нищие существование MySQL.

DeimoS
10.09.2017, 11:02
Про какие рамки ты все время говоришь? Алгоритм выше генерирует все возможные значения для этих самых 6 значений. Соответственно, будет все также, как и без таблицы.

Когда следует забирать номер - это уже дело конечного разработчика системы. Наиболее очевидные - при удалении аккаунта (достаточно просто из таблицы номеров). В конечном итоге разницы между с таблицей номеров и без неё - не будет. Разве что, без зависания сервера и отправкой кучи запросов в никуда. Ах да, и самое главное - без написания каких то безумных и никому ненужных алгоритмов на генерацию нужного тебе номера.

По поводу твоего алгоритма - я вообще сути не понимаю. Допустим, можно сделать так, что бы генерируемые значения не повторялись, окей. Можно еще сделать так, что бы те номера, которые уже на сервере, не попадали в генерацию - окей. И что еще? Да ничего, в итоге мы получаем непонятный код, который в + к запросам будет тратить драгоценное процессорное время. А запросов то в конечном итоге меньше не стало..

Единственный способ, сделать без таблицы адекватный вариант, это сделать все по порядку. Без таблицы, без всяких заморочек, в виде алгоритма и т.д. Но как это без рандома? Кто будет играть на таком сервере?

У меня уже нет желания участвовать в этой полемике, так что переубеждать я тебя не собираюсь. Любишь извращения - пожалуйста. Я донёс свою мысль и на этом всё.

Одно лишь хочу заметить: как ты плавно перешёл от рассуждений о моём безумстве к рассуждениям о том, кто и на каких серверах играет. А выводы из этой информации пусть каждый сам для себя сделает :)

Автору темы просьба отписаться: получен ли ответ или нет.

M1RoN
15.09.2017, 06:05
Да, ответ получен, спасибо
Можно закрывать тему