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

Zippy

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

Zippy

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

Zippy

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

WebBot

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

marushin

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

BAZAg

Client
Регистрация
08.11.2015
Сообщения
1 515
Благодарностей
2 063
Баллы
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
Сообщения
144
Благодарностей
39
Баллы
28
Ну, и конечно, возможно я ошибся в расчётах...
P.S. Точно ошибся - результат ещё нужно на 100 поделить - получится, что в 100 потоков просто в 100 раз быстрее работа выполнится, но, пропорции издержек сохранятся.
Время потраченное для 100 одновременных запросов к БД не равно время1-го запроса *100
БД параллельно обрабатывает запросы
 
  • Спасибо
Реакции: BAZAg

BAZAg

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

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

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

marushin

Client
Регистрация
12.01.2015
Сообщения
144
Благодарностей
39
Баллы
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 515
Благодарностей
2 063
Баллы
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
Сообщения
144
Благодарностей
39
Баллы
28
В момент между BEGIN; и COMMIT; база пытается зафиксировать состояние.
В этот конкретный момент все остальные обращения стоят в очереди, курят, девок по кабакам водят и тп.
Если скорость добавления запросов в очередь больше, чем скорость обработки очереди - к чему это приводит?
Ничего не стоит, локается запись, а не таблица. И если таблица правильно составлена, то параллельно запросы обрабатываются.
 
  • Спасибо
Реакции: BAZAg

BAZAg

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

marushin

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

olek2765

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

volody00

Client
Регистрация
06.09.2016
Сообщения
628
Благодарностей
651
Баллы
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
Сообщения
64
Благодарностей
23
Баллы
8
Подскажите логику, есть база логин: пароль: статус (в работе и свободен)
Я беру по статусу строку в работу со статусом свободен, после ставлю статус в работе, в один поток работает норм но когда несколько потоков получаеться что несколько потоков берут одну и ту жу строку. Как исправить?
я кубиком беру, по условию что акк не в работе (1 условие), акк активный (2 условие) - из всей выборки 1 строку кидаю в переменные

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

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

GreenWay

Client
Регистрация
11.05.2012
Сообщения
386
Благодарностей
118
Баллы
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
Сообщения
64
Благодарностей
23
Баллы
8
Какую БД используешь?
Предполагаю что БД SQLite, по количеству строк она очень скромная) Находится на хостинге где сайты храню. Подойдет ли для твоих задач такой вариант - не подскажу
 

ильяsffse

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

Phoenix78

Client
Регистрация
06.11.2018
Сообщения
10 734
Благодарностей
5 120
Баллы
113

Phoenix78

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

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