Имя пользователя:
Пароль:  
Помощь | Регистрация | Забыли пароль?  | Правила  

Компьютерный форум OSzone.net » Программирование, базы данных и автоматизация действий » Программирование и базы данных » MySQL - Помогите оптимизировать запросы!

Ответить
Настройки темы
MySQL - Помогите оптимизировать запросы!

Пользователь


Сообщения: 78
Благодарности: 5

Профиль | Отправить PM | Цитировать


Здравствуйте!

Будучи любителем, разрабатываю один продукт на MySQL, вставшая задачка разрослась далеко за любительский уровень...

В числе прочего, в базе есть таблица, имеющая тенденцию сильно "распухать". Сейчас в нее добавляется порядка 2000-3000 новых записей в день, и это по идеологии проекта еще очень мало. Не исключено возрастание наполняемости до 100000-1000000 новых записей в день. Очень бы хотелось хранить эту таблицу (это полный ЛОГ событий и транзакций системы) в полном объеме.

1. Подскажите - не маразм ли это идеологически? Одна таблица с сотнями миллиардов записей и больше?
2. Встает очевидная проблема - уже сейчас. Время запроса к такой таблице. Сейчас у меня сделано любительски (я только начинаю осваивать ЭТО) - внутри цикла WHILE крутится сначала SELECT-запрос - это проверка уникальности новой записи. Если SELECT возвращает нулевой результат - происходит INSERT INTO. Мне подсказали, что делать внутри внешнего цикла каскад подобных запросов - дурь, что можно делать один запрос, а весь каскад проверок может сделать сама СУБД, за время в сотню раз меньше...
Подскажите, реально ли это? Посоветуйте про какие операторы мануалы изучать?)) Или книжку хорошую... Использую РНР и чистый С, с акцентом на второй.

3. Какое типичное время одиночного запроса следует ожидать при размере таблицы допустим, в сотню миллиардов строк? При таком раскладе можно будет только под БД выделить отдельный XEON-сервер.

С уважением, Евгений

Отправлено: 10:53, 21-05-2015

 

Ветеран


Сообщения: 27449
Благодарности: 8087

Профиль | Отправить PM | Цитировать


Цитата evpu:
внутри цикла WHILE крутится сначала SELECT-запрос - это проверка уникальности новой записи. Если SELECT возвращает нулевой результат - происходит INSERT INTO. »
Если это лог — зачем проверка на уникальность, причём всей записи? Почему не использовать в качестве ключа просто автоинкрементный идентификатор-счётчик?

Отправлено: 11:45, 21-05-2015 | #2



Для отключения данного рекламного блока вам необходимо зарегистрироваться или войти с учетной записью социальной сети.

Если же вы забыли свой пароль на форуме, то воспользуйтесь данной ссылкой для восстановления пароля.


Аватара для lxa85

Необычный


Contributor


Сообщения: 4466
Благодарности: 994

Профиль | Сайт | Отправить PM | Цитировать


Цитата evpu:
Сейчас у меня сделано любительски »
описание действительно звучит подозрительно. Т.к. принципы работы СУБД отличаются от принципов работы с массивом в его каноническом понимании.
Задавать операции принудительного перебора строк таблицы - ведет к катастрофическому падению производительности системы.
Не ради рекламы будет сказано: сегодня-завтра проходит выставка российских интернет технологий, в частности представлена секция HighLoad. Насколько будет оправдан входной билет стоиомстью в 21 рубль - не знаю. Но жадный хоботок можно опустить в мозги тем людям.

По факту же надо смотреть конкретно. Устройство таблиц, используемый движок и пр.
BTW как вариант поднятия собственного скила разработчика - поищите фирменный Оракловский цикл передач, посвященных работе с СУБД.

КАк вариант "за что купил".
Есть системы СУБД, которые размещаются в оперативной памяти. По быстродействию, они, разумеется впереди планеты всей. Соотв. выделить n'цать Гб под "оперативный" лог, остальное в архив.

Я боюсь, что при переходе с любительского на профессиональный уровень придется довольно сильно перекраивать внутреннюю архитектуру системы.

Как вариант, посмотрите диагонально протоколы FIX, FAST используемые на фондовых биржах. Это может быть не совсем "лог", но возможно идеи будут полезны.

Столь стремительное возрастание запросов - а сеть выдержит данный поток?

P.S.
Это всего лишь поток сознания! Соотв. относиться к нему надо с должным пониманием и опаской

-------
- Я не разрешаю тебе быть плохой! Потому что плохие люди совершают плохие поступки. А это нехорошо!
(Из наставлений 5 летней девочки своей младшей сестре)


Отправлено: 11:49, 21-05-2015 | #3


Пользователь


Сообщения: 78
Благодарности: 5

Профиль | Отправить PM | Цитировать


>>зачем проверка на уникальность, причём всей записи?

Прежде чем событие будет занесено в базу - оно поступает с удаленного устройства. По протоколу, который из соображений целостности имеет избыточность - т.е комбинация "место-время-человек" являющаяся уникальной, может поступить несколько раз, или из одного, или из нескольких физических каналов, но в базу одно и то же событие должно заноситься один раз, в данном случае с проверкой по всем трем полям, так как только их комбинация является уникальной. Для этого, перед INSERT INTO делаю SELECT, если последний не равен 0 - текущие данные отбрасываются, и далее по циклу. При INSERT INTO разумеется, событие обрастает уникальным ID, и флагом того, что оно только занесено - но еще не обработано, и уже из базы извлекается под уникальным номером.
А ПОТОМ - уже другое приложение извлекает запись с пометкой "не обработано", обрабатывает, и производит UPDATE всей строки, в которой помимо полей "id-место-время-человек-флаг" есть еще поля, типа "место события на человеческом языке", "имя на человеческом языке", "списанная сумма" и.т.д.

А потом - человек сам, на сайте вводит содержимое поля "человек" (цифровой аккаунт), и лимит вывода - и получает ответ (детализацию) событий по своему лицевому счету, на человеческом языке. Т.е крохотную выборку из потенциально многомиллиардной общей БД. Все это уже создано, и работает. Но пока не поздно надо переделать - т.к обработка суточных 3000 событий занимает уже 8-10 минут при кол-ве строк ~120000. Я не прошу решить мне задачу - подскажите где копать!))

Отправлено: 12:19, 21-05-2015 | #4


Пользователь


Сообщения: 78
Благодарности: 5

Профиль | Отправить PM | Цитировать


>>Столь стремительное возрастание запросов - а сеть выдержит данный поток?

Под такой поток - можно сервер в датацентр загнать. Устройство цепляется по ТСР с использованием accept() т.е ожидается нагрузочная способность не хуже чем у apache. 1000000 соединений в сутки это около 11 в секунду... Нормальный сервер должен выдержать... и БД сервер в.т.ч. Или accept-сервер расщепить на несколько по слабее, наибольший упор сделав на БД. Но это мечты, но мечтаю я по полной...

Отправлено: 12:40, 21-05-2015 | #5


Аватара для lxa85

Необычный


Contributor


Сообщения: 4466
Благодарности: 994

Профиль | Сайт | Отправить PM | Цитировать


Цитата evpu:
Я не прошу решить мне задачу - подскажите где копать!) »
Так в отсутствии конкретики, мы этим и занимаемся
Возможно имеет смысл провести еще одну нормализацию и выделить еще пару таблиц для работы с "человеческим описанием"?
+ Введение максимального количества цифр. Т.к. операции численного сравнения будут быстрее, чем символьного.
Получится что лог - будет сборником идентификаторов.
Цитата evpu:
3000 событий занимает уже 8-10 минут при кол-ве строк ~120000 »
Это перебор.

Кстати, а как именно выглядит процедура?
На каждую из 3000 строк происходит поиск SELECT по все таблице?
Т.е.
Код: Выделить весь код
While 1 - 3000 
   Select * FROM Table
If 0 Then INSERT
?

-------
- Я не разрешаю тебе быть плохой! Потому что плохие люди совершают плохие поступки. А это нехорошо!
(Из наставлений 5 летней девочки своей младшей сестре)


Отправлено: 13:00, 21-05-2015 | #6


Ветеран


Сообщения: 27449
Благодарности: 8087

Профиль | Отправить PM | Цитировать


evpu, примерно так вижу:
  1. Выделить под сбор отдельную таблицу с полями: ID, и первичным ключом из трёх полей «место-время-человек». Всё прочее вынести в отдельную таблицу, имеющую по ID целостную связь 1:1 с первой.
  2. Как уже писал выше, в первой таблице сделать первичный ключ из трёх полей «место-время-человек». Никаких проверок select'ом перед вставкой не производить вовсе — это задача базы данных проверить и отвергнуть операцию добавления записи с дублирующим первичным ключом (надеюсь, MySQL умеет сие, не работал с ним программно).
P.S. Как Вы понимаете, это примерная схема. Не зная предметной области, не зная деталей трудно советовать что-либо конкретное. Например, тот же флаг обработки — держать в первой или во второй таблице?!
Это сообщение посчитали полезным следующие участники:

Отправлено: 13:33, 21-05-2015 | #7


Пользователь


Сообщения: 78
Благодарности: 5

Профиль | Отправить PM | Цитировать


>>While 1 - 3000
>> Select * FROM Table
>>If 0 Then INSERT

Именно. Типа того.

Именно про такую конструкцию один мой знакомый говорил, что подобные циклы можно заставить обрабатывать в самой СУБД, не делая каскада запросов. Но как это сделать - он не знает.

>>Выделить под сбор отдельную таблицу с полями: ID, и первичным ключом из трёх полей «место-время-человек». Всё >>прочее вынести в отдельную таблицу, имеющую по ID целостную связь 1:1 с первой.

В общих чертах понял о чем Вы, но принципиальная проблема не устраняется - при распухании всей таблицы, распухает и эта часть. Т.е делать или не делать отдельно - по сути - не особо важно.

Т.е насколько я понял, сочетание полей «место-время-человек» может быть уникальным 3-мя полями отдельно (а точнее 4 - место состоит из 2-х частей)?? Тогда, можно проще - я сырую строку прилетающую из аппаратуры включающую в себя эти 3 компонента для простоты разбиваю на 3 поля, а могу ведь этого не делать - загонять в базу одним общим полем "raw_string" - которое и должно быть уникальным...
И что - при 2-х кратном INSERT одного и того же, дубликат может быть отвергнут самой БД??? Круто... Попробую.
На эту тему последнее - а можно в одном запросе послать не 1 INSERT а сразу кучу (15-20 и более)? А уж БД в процессе сама разберется с уникальностью...

Отправлено: 20:46, 21-05-2015 | #8


Ветеран


Сообщения: 27449
Благодарности: 8087

Профиль | Отправить PM | Цитировать



Цитата evpu:
но принципиальная проблема не устраняется - при распухании всей таблицы, распухает и эта часть. »
Не скажите. Есть некоторая разница, пробегаться движку по N размеру таблицы или по NxM размеру, даром что там и там выбираете одно и то же количество полей. Вы можете, кстати, проверить, ведь у Вас есть готовая таблица.

Цитата evpu:
Т.е насколько я понял, сочетание полей «место-время-человек» может быть уникальным 3-мя полями отдельно (а точнее 4 - место состоит из 2-х частей)?? »
Э… Откуда ж мне знать Вашу предметную область? Так именно Вы выше написали, и именно так я и понял.

Цитата evpu:
Тогда, можно проще - я сырую строку прилетающую из аппаратуры включающую в себя эти 3 компонента для простоты разбиваю на 3 поля, а могу ведь этого не делать - загонять в базу одним общим полем "raw_string" - которое и должно быть уникальным... »
Не уверен, что сие будет правильным. Впрочем, Вам на месте виднее будет.

Цитата evpu:
И что - при 2-х кратном INSERT одного и того же, дубликат может быть отвергнут самой БД??? Круто... Попробую. »
Вот Вам для примера база Microsoft Access: Sample.7z. Для простоты взяты «место» и «человек» как простой текст (если могут повторяться, то они обязаны содержаться в отдельных таблицах, куда из записи основной таблицы должны вести ссылки). Первичным ключом таблицы «Таблица1» является тройка полей «место-время-человек».

При исполнении кода процедуры из «Модуль1» производится попытка вставки четырёх записей поочерёдно отдельными запросами «INSERT INTO … VALUES», причём третий и четвёртый запросы — дублируют по VALUES первый и второй.

Так вот, будет вставлено только две записи по первому и второму запросам. А по третьему и четвёртому — вставка записи будет отвергнута, поскольку недопустимо дублирование первичного ключа.

Разумеется, это Jet и Access. Как там обстоят дела в MySQL, я не знаю, не пробовал. Но общие принципы построения реляционных баз данных должны быть одинаковы для всех.

Цитата evpu:
а можно в одном запросе послать не 1 INSERT а сразу кучу (15-20 и более)? »
Можно, «INSERT INTO … SELECT … FROM …». Но, как я понимаю, Вам это не подойдёт.

Отправлено: 21:28, 21-05-2015 | #9


Аватара для lxa85

Необычный


Contributor


Сообщения: 4466
Благодарности: 994

Профиль | Сайт | Отправить PM | Цитировать


Цитата evpu:
>>While 1 - 3000
>> Select * FROM Table
>>If 0 Then INSERT
Именно. Типа того. »
Подобный подход действительно роняет производительность СУБД в ноль
СУБД работает не с массивами, СУБД работает с множествами.
Запомните как мантру! (искренне не в обиду)
Любой итерационный подход - табу!

У вас есть таблица лога, есть основная таблица.
Вы делаете пересечение таблиц (Join_(SQL)) с необходимыми параметрами.
Получаете дельту и уже ее добавляете к основной таблице.
Кстати!
Merge
Объединение двух таблиц с условием. Тут отдельно стоит уточнить вопросы блокировки таблиц. Краем глаза видел слова в описаниях, но досконально не выяснял.

-------
- Я не разрешаю тебе быть плохой! Потому что плохие люди совершают плохие поступки. А это нехорошо!
(Из наставлений 5 летней девочки своей младшей сестре)


Отправлено: 22:54, 21-05-2015 | #10



Компьютерный форум OSzone.net » Программирование, базы данных и автоматизация действий » Программирование и базы данных » MySQL - Помогите оптимизировать запросы!

Участник сейчас на форуме Участник сейчас на форуме Участник вне форума Участник вне форума Автор темы Автор темы Шапка темы Сообщение прикреплено

Похожие темы
Название темы Автор Информация о форуме Ответов Последнее сообщение
PowerShell - [решено] Как оптимизировать User001 Скриптовые языки администрирования Windows 1 10-04-2014 09:54
CMD/BAT - помогите оптимизировать скрипт dredre Скриптовые языки администрирования Windows 1 18-09-2011 05:10
помогите оптимизировать систему BABA ZINA Выбор отдельных компонентов компьютера и конфигурации в целом 6 07-01-2011 22:19
Помогите оптимизировать офис. Голова пухнит Joni Флейм 11 19-08-2009 11:55
CMD/BAT - Помогите оптимизировать код n4! Скриптовые языки администрирования Windows 3 08-04-2008 05:59




 
Переход