Базы данных на пальцах (для новичков)

Zippy

Client
Регистрация
14.12.2021
Сообщения
64
Благодарностей
6
Баллы
8
Хороший совет. Напарсить данных в БД, создать сайт на миллион паг, вложить много тыщ в SEO, а потом узнать, что статьи не лезут в ТОП потому что в них обрезан контент, который нет возможности восстановить.
Мне кажется при описанных масштабах уже многие грабли будут пройдены)
 

Zippy

Client
Регистрация
14.12.2021
Сообщения
64
Благодарностей
6
Баллы
8
В общем, метод тыка наверно не плох, в начале, но, думаю, лучше знать базовые типы, varchar, text, int, float.
 

Zippy

Client
Регистрация
14.12.2021
Сообщения
64
Благодарностей
6
Баллы
8
Допустим у меня есть база с таблицей emails: mail, password, works, banned и мне нужно взять из этой таблицы почту+пароль, рабочие, не забаненые, только с доменом yandex.ru. Пишу соответствующий запрос к БД в кубике. Получившийся результат, допустим 100 аккаунтов, мне нужно скормить регистратору. Какой подход более грамотный - сделать запрос один раз в начале проекта и сохранить результат в список и брать из списка по одной строчке каждый новый цикл или написать запрос так, чтобы он по очереди выдавал только одну строку в переменную каждый новый цикл и уже регистратор будет брать почту из этой перменной?
 

WebBot

Client
Регистрация
04.04.2015
Сообщения
1 713
Благодарностей
1 370
Баллы
113
Допустим у меня есть база с таблицей emails: mail, password, works, banned и мне нужно взять из этой таблицы почту+пароль, рабочие, не забаненые, только с доменом yandex.ru. Пишу соответствующий запрос к БД в кубике. Получившийся результат, допустим 100 аккаунтов, мне нужно скормить регистратору. Какой подход более грамотный - сделать запрос один раз в начале проекта и сохранить результат в список и брать из списка по одной строчке каждый новый цикл или написать запрос так, чтобы он по очереди выдавал только одну строку в переменную каждый новый цикл и уже регистратор будет брать почту из этой перменной?
самое оптимальное делать регистратор так что бы 1 запуск регал 1 аккаунт и соответственно брал из БД для этого 1 строку
 
  • Спасибо
Реакции: BAZAg

marushin

Client
Регистрация
12.01.2015
Сообщения
185
Благодарностей
55
Баллы
28
Допустим у меня есть база с таблицей emails: mail, password, works, banned и мне нужно взять из этой таблицы почту+пароль, рабочие, не забаненые, только с доменом yandex.ru. Пишу соответствующий запрос к БД в кубике. Получившийся результат, допустим 100 аккаунтов, мне нужно скормить регистратору. Какой подход более грамотный - сделать запрос один раз в начале проекта и сохранить результат в список и брать из списка по одной строчке каждый новый цикл или написать запрос так, чтобы он по очереди выдавал только одну строку в переменную каждый новый цикл и уже регистратор будет брать почту из этой перменной?
Лучше для каждого действия свой запрос, так можно промежуточные данные вносить и если несколько потоков, то не получится, что разные потоки с одним и тем же аком работают. Но если БД учавствует в разных проектах или БД довольно большая, то меньше обращений лучше. Тут уже по ситуации смотреть, просто БД может не успевать обрабатыать запросы. В зенковском кубике, как я понял, есть ограничение на время ожидания ответа от БД.
 
Последнее редактирование:
  • Спасибо
Реакции: BAZAg

BAZAg

Client
Регистрация
08.11.2015
Сообщения
1 758
Благодарностей
2 392
Баллы
113
Допустим у меня есть база с таблицей emails: mail, password, works, banned и мне нужно взять из этой таблицы почту+пароль, рабочие, не забаненые, только с доменом yandex.ru. Пишу соответствующий запрос к БД в кубике. Получившийся результат, допустим 100 аккаунтов, мне нужно скормить регистратору. Какой подход более грамотный - сделать запрос один раз в начале проекта и сохранить результат в список и брать из списка по одной строчке каждый новый цикл или написать запрос так, чтобы он по очереди выдавал только одну строку в переменную каждый новый цикл и уже регистратор будет брать почту из этой перменной?
Если, мы работаем в 1 поток, внутри шаблона, тогда:

Запрос к базе, к примеру 10 секунд.
Регистрация аккаунта, например 100 секунд.
В случае если мы возьмем 1 запросом 100 строчек - наши накладные затраты по времени = 10 секунд.
Остальное время - полезные действия (например регистрация).
В конце работы - отчитываемся перед базой - ещё 1 запрос.
Вместе накладных расходов 20 секунд времени.
Итого, спустя 100*100+20 = 10 020 секунд мы получим наши аккаунты.
В этом соотношении накладные расходы составили 0,2%.
Спустя это время мы получим 100 аккаунтов.

Рассмотрим аналогичную ситуацию, но, на каждом запросе мы получаем 1 строчку.
Тогда 100*100+20*100 = 12 000 секунд мы получим наши аккаунты.
В этом соотношении - накладные расходы составили 20%.
Спустя это время мы получим 100 аккаунтов.

Если, мы работаем в 100 потоков, тогда:
Может показаться, что вот, если мы будем работать в многопоточном режиме, то ситуация изменится кардинально.
Нужно смоделировать ситуацию примерно так - каждый отдельный поток будет работать какое-то время, и зарегистрирует нам 100 аккаунтов.
Тогда, если мы запускаем 100 потоков одновременно, получим такой расчёт:
В первом случае: 100*100*100 + 20*100 = 1 002 000 секунд.
Во втором случае: 100*100*100 + 20*100*100 = 1 200 000 секунд.
Итого, спустя это время мы получим 10 000 аккаунтов.

Ну, и конечно, возможно я ошибся в расчётах...
P.S. Точно ошибся - результат ещё нужно на 100 поделить - получится, что в 100 потоков просто в 100 раз быстрее работа выполнится, но, пропорции издержек сохранятся.
 
Последнее редактирование:
  • Спасибо
Реакции: Zippy и marushin

marushin

Client
Регистрация
12.01.2015
Сообщения
185
Благодарностей
55
Баллы
28
Ну, и конечно, возможно я ошибся в расчётах...
P.S. Точно ошибся - результат ещё нужно на 100 поделить - получится, что в 100 потоков просто в 100 раз быстрее работа выполнится, но, пропорции издержек сохранятся.
Время потраченное для 100 одновременных запросов к БД не равно время1-го запроса *100
БД параллельно обрабатывает запросы
 
  • Спасибо
Реакции: BAZAg

BAZAg

Client
Регистрация
08.11.2015
Сообщения
1 758
Благодарностей
2 392
Баллы
113
Время потраченное для 100 одновременных запросов к БД не равно время1-го запроса *100
БД параллельно обрабатывает запросы
В теории - БД работает параллельно ( сообщенька на первой страничке)
На практике, мы не можем вместо 100 подставить значение 1 000 000 000 000 или бесконечность (разве что говорим о какой-то микросервисной архитектуре).
Попробуйте погонять многопоток без локов например с SQLite, или например хотя бы в 100 потоков MySQL, если в таблицах хранится например 1-2 ГБ данных.

Ну, и если все так хорошо с параллельностью - вопрос сразу такой - почему же на форуме люди все же говорят о локах, транзакциях и тп?

Что касается конкретно совета пользователю, которому он понадобился - решается все просто - пишем бота, который перед регистрацией берет данные с базы, а после регистрации - отчитывается.
А когда в процессе будет ощущаться подход к ограничениям базы (например превышено количество подключений к базе и тп) - тогда просто меняем логику на то, чтобы взять с базы 1000 строк, и работать с ними, а после отработки - вернуть результат в базу сразу пачкой.
Если же в процессе нужно отслеживать ещё статусы на каком шаге сейчас регистрация того или иного аккаунта - тогда от единичных запросов никуда деться не получится - с ними нужно будет смириться :-)
 
Последнее редактирование:
  • Спасибо
Реакции: marushin

marushin

Client
Регистрация
12.01.2015
Сообщения
185
Благодарностей
55
Баллы
28
Попробуйте погонять многопоток без локов например с SQLite, или например хотя бы в 100 потоков MySQL, если в таблицах хранится например 1-2 ГБ данных.

Ну, и если все так хорошо с параллельностью - вопрос сразу такой - почему же на форуме люди все же говорят о локах, транзакциях и тп?
Именно по опыту работы с MySQL и делаю выводы.
1 сервер MySQL в локалке, несколько БД с записями 10-50КК, в 25 потоков с одного компа, 5-10 потоков с другого. Не сказать что летает в пике, но работает стабильно.

Запросы с локами по такой схеме делаю:

BEGIN;
SET @v1 = (
SELECT id_table FROM my_table WHERE task_done = 0 LIMIT 1 FOR UPDATE);
DELETE FROM my_table WHERE id_table = @v1;
Select @v1;
COMMIT;

предложенно в этой теме Извлечь строку из таблицы БД MySQL
т.е. локается не таблица, а запись
 
  • Спасибо
Реакции: BAZAg

BAZAg

Client
Регистрация
08.11.2015
Сообщения
1 758
Благодарностей
2 392
Баллы
113
Именно по опыту работы с MySQL и делаю выводы.
1 сервер MySQL в локалке, несколько БД с записями 10-50КК, в 25 потоков с одного компа, 5-10 потоков с другого. Не сказать что летает в пике, но работает стабильно.

Запросы с локами по такой схеме делаю:

BEGIN;
SET @v1 = (
SELECT id_table FROM my_table WHERE task_done = 0 LIMIT 1 FOR UPDATE);
DELETE FROM my_table WHERE id_table = @v1;
Select @v1;
COMMIT;

предложенно в этой теме Извлечь строку из таблицы БД MySQL
В момент между BEGIN; и COMMIT; база пытается зафиксировать состояние.
В этот конкретный момент все остальные обращения стоят в очереди, курят, девок по кабакам водят и тп.
Если скорость добавления запросов в очередь больше, чем скорость обработки очереди - к чему это приводит?

Я не говорю, что так делать не нужно - сам также делаю.
Но, если к примеру у меня в базе 1кк почт или доменов, и мне нужно их проверить на существование, то глупо делать это по 1 почте.
Куда выгоднее взять 1000, в параллельных потоках отправить нужные запросы, и уже потом просто сохранить результат 1 запросом в базу.

Другими словами - если мы берем и возвращаем данные например 1 раз в минуту, в 100 потоков - все ок.
Если нам придется брать/добавлять/изменять больше в минуту - тогда нужно задуматься о том, чтобы группировать.
 
  • Спасибо
Реакции: marushin

marushin

Client
Регистрация
12.01.2015
Сообщения
185
Благодарностей
55
Баллы
28
В момент между BEGIN; и COMMIT; база пытается зафиксировать состояние.
В этот конкретный момент все остальные обращения стоят в очереди, курят, девок по кабакам водят и тп.
Если скорость добавления запросов в очередь больше, чем скорость обработки очереди - к чему это приводит?
Ничего не стоит, локается запись, а не таблица. И если таблица правильно составлена, то параллельно запросы обрабатываются.
 
  • Спасибо
Реакции: BAZAg

BAZAg

Client
Регистрация
08.11.2015
Сообщения
1 758
Благодарностей
2 392
Баллы
113
Ничего не стоит, локается запись, а не таблица. И если таблица правильно составлена, то параллельно запросы обрабатываются.
Таблица нам дана: emails: mail, password, works, banned
Она правильно составлена, чтобы параллельно обрабатывать запросы?
Или речь идет именно о поле key по которому должен быть построен индекс?
 

marushin

Client
Регистрация
12.01.2015
Сообщения
185
Благодарностей
55
Баллы
28
Таблица нам дана: emails: mail, password, works, banned
Она правильно составлена, чтобы параллельно обрабатывать запросы?
У полей есть индексы, от правильности проставки или не проставки индексов будет зависеть скорость на больших таблицах.
 
  • Спасибо
Реакции: BAZAg

olek2765

Client
Регистрация
28.12.2018
Сообщения
10
Благодарностей
0
Баллы
1
Подскажите логику, есть база логин: пароль: статус (в работе и свободен)
Я беру по статусу строку в работу со статусом свободен, после ставлю статус в работе, в один поток работает норм но когда несколько потоков получаеться что несколько потоков берут одну и ту жу строку. Как исправить?
 

volody00

Client
Регистрация
06.09.2016
Сообщения
792
Благодарностей
810
Баллы
93
Подскажите логику, есть база логин: пароль: статус (в работе и свободен)
Я беру по статусу строку в работу со статусом свободен, после ставлю статус в работе, в один поток работает норм но когда несколько потоков получаеться что несколько потоков берут одну и ту жу строку. Как исправить?
https://zennolab.com/discussion/threads/pomogite-postroit-logiku-raboty-s-bd-i-ee-lokom-mnogopotok.106165/post-703168 , https://zennolab.com/discussion/threads/mysql-vzjat-unikalnuju-stroku-i-obnovit-tranzakcija.36704/post-272886

можешь эти варианты попробовать. Я сам лочу через c#, но также можно составлять более продвинутые sql запросы, где ты одним запросом и отберешь аккаунт и дашь статус busy.
 
  • Спасибо
Реакции: olek2765 и seodamage
Регистрация
21.07.2021
Сообщения
77
Благодарностей
30
Баллы
18
Подскажите логику, есть база логин: пароль: статус (в работе и свободен)
Я беру по статусу строку в работу со статусом свободен, после ставлю статус в работе, в один поток работает норм но когда несколько потоков получаеться что несколько потоков берут одну и ту жу строку. Как исправить?
я кубиком беру, по условию что акк не в работе (1 условие), акк активный (2 условие) - из всей выборки 1 строку кидаю в переменные

Вторым кубиком ставлю статус в работе > для этого акка

Не сильно много потоков, кубик БД может работать в многопотоке - в тех.поддержке уточнял.
 
  • Спасибо
Реакции: GreenWay и olek2765

GreenWay

Client
Регистрация
11.05.2012
Сообщения
423
Благодарностей
132
Баллы
43
я кубиком беру, по условию что акк не в работе (1 условие), акк активный (2 условие) - из всей выборки 1 строку кидаю в переменные

Вторым кубиком ставлю статус в работе > для этого акка

Не сильно много потоков, кубик БД может работать в многопотоке - в тех.поддержке уточнял.
Какую БД используешь?
Например БД SQLite (на 300 000 строк) при 5 параллельных потоках простой запрос-проверка пола по имени (пример запроса)
C#:
SELECT GENDER FROM BASE WHERE NAME LIKE ('{-Variable.NAME-} %') LIMIT 1
Иногда отдает пустоту, хотя строка "NAME-GENDER" присутствует.
И вот еще вопрос-проблема.. Я беру имя, перевожу в нижний регистр и ищу по базе - забираю гендер. Если не находит - то возвращает пустоту. Но из-за многопотока иногда отдает пустоту даже при наличии "NAME-GENDER". Можно ли как-то иначе проверять? Может чтоб статус отдавало а не просто пустоту..
 
Последнее редактирование:
Регистрация
21.07.2021
Сообщения
77
Благодарностей
30
Баллы
18
Какую БД используешь?
Предполагаю что БД SQLite, по количеству строк она очень скромная) Находится на хостинге где сайты храню. Подойдет ли для твоих задач такой вариант - не подскажу
 

ильяsffse

Client
Регистрация
23.06.2018
Сообщения
113
Благодарностей
50
Баллы
28
SQLite После удаления строк НЕ меняет размер файла :bh:
Что делать ???
VACUUM ? rowid он нарушить может-нарушает???
Кто шарит подскажите пж:ce:
 

Phoenix78

Client
Read only
Регистрация
06.11.2018
Сообщения
11 790
Благодарностей
5 683
Баллы
113

ильяsffse

Client
Регистрация
23.06.2018
Сообщения
113
Благодарностей
50
Баллы
28

Phoenix78

Client
Read only
Регистрация
06.11.2018
Сообщения
11 790
Благодарностей
5 683
Баллы
113
Так а как при удалении строки... освобождать место :bh:
Весит с данными 10мб и после удаления сток 10мб. даже если пусто.. шо за дела:ce:o_O
удаление строк, это чисто метка в базе. сами данные остаются в базе. поэтому она только растет в размере. зато операция быстро проходит.
VACUUM удаляет эти старые данные.
у меня база используется эпизодически и перед началом работы с ней я ее чищу вот так
PRAGMA integrity_check;
VACUUM;
 
  • Спасибо
Реакции: ильяsffse

Nekro

Client
Регистрация
01.08.2020
Сообщения
223
Благодарностей
22
Баллы
18
Подскажите, такое подключение ещё актуально? Через HeidiSQL подключаюсь нормально, а в ZP не получается. Насыпает ошибки. У меня ещё порт нестандартный. Как его прописать? БД MySQL на Windows Server.

SQL:
Data source=то_что_мы_вводили_в_имя_хоста;UserId=логин_jino;Password=пароль_jino;database=имяБД;Charset=utf8;
114987

114986
 
Регистрация
21.07.2021
Сообщения
77
Благодарностей
30
Баллы
18
В ковычках проблема может быть
Сам такое же действие в HeidiSQL сделай, скопируй запрос в зенку в поле "Текст запроса"
Насчет порта тут не скажу.

Все запросы с HeidiSQL вставляю в зенку, и дальше уже вставляю переменные - все работает
114999
 
  • Спасибо
Реакции: Nekro

Nekro

Client
Регистрация
01.08.2020
Сообщения
223
Благодарностей
22
Баллы
18
В ковычках проблема может быть
Сам такое же действие в HeidiSQL сделай, скопируй запрос в зенку в поле "Текст запроса"
Насчет порта тут не скажу.

Все запросы с HeidiSQL вставляю в зенку, и дальше уже вставляю переменные - все работает
Посмотреть вложение 114999
В расширенных настройках выставил Port, сама строка подключения значительно изменилась. После этого - заработало.
115001
 

SanchoPancho

Client
Регистрация
09.12.2015
Сообщения
160
Благодарностей
82
Баллы
28
/* Пример вставки сразу нескольких значений */
INSERT INTO zennolab (name, age) VALUES('pety','24'), ('koly','42');

Подскажите пожалуйста как передать массив данных например из таблицы или списка?
 
Последнее редактирование:

Alex733

Client
Регистрация
27.11.2017
Сообщения
316
Благодарностей
230
Баллы
43
/* Пример вставки сразу нескольких значений */
INSERT INTO zennolab (name, age) VALUES('pety','24'), ('koly','42');

Подскажите пожалуйста как передать массив данных например из таблицы?
Надо преобразовать массив данных в строку. Например, можно так:

C#:
var zt = project.Tables["tmp"];
string tosql = "";

for(int i = 0; i < zt.RowCount; i++){
    string name = zt.GetCell("A",i);
    string age = zt.GetCell("B",i);
    tosql += $"('{name}', '{age}'),";
}
return "INSERT INTO zennolab (name, age) VALUES " + tosql.Trim(',');
 
Последнее редактирование:
  • Спасибо
Реакции: SanchoPancho

SanchoPancho

Client
Регистрация
09.12.2015
Сообщения
160
Благодарностей
82
Баллы
28
Надо преобразовать массив данных в строку. Например, можно так:

C#:
var zt = project.Tables["tmp"];
string tosql = "";

for(int i = 0; i < zt.RowCount; i++){
    string name = zt.GetCell("A",i);
    string age = zt.GetCell("B",i);
    tosql += $"('{name}', '{age}'),";
}
return "INSERT INTO zennolab (name, age) VALUES " + tosql.Trim(',');
Спасибо, то что нужно!
 

Кто просматривает тему: (Всего: 2, Пользователи: 1, Гости: 1)