OberonCore

Библиотека  Wiki  Форум  BlackBox  Компоненты  Проекты
Текущее время: Воскресенье, 22 Сентябрь, 2019 15:57

Часовой пояс: UTC + 3 часа




Начать новую тему Ответить на тему  [ Сообщений: 39 ]  На страницу Пред.  1, 2
Автор Сообщение
 Заголовок сообщения: Re: Mysql
СообщениеДобавлено: Суббота, 21 Июнь, 2014 18:15 
Администратор

Зарегистрирован: Вторник, 15 Ноябрь, 2005 01:14
Сообщения: 4302
Откуда: Россия, Орёл
Какой-то бред.
Операторы через ";" выполняются только для консольного клиента mysql и там являются частью его входного синтаксиса, в том числе и для дампов. ";" не входит в диалект SQL, который поддерживается в MySQL.
Так что никакая эта не важная особенность. Это из разряда "а вот мне захотелось фичу прикрутить".


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Mysql
СообщениеДобавлено: Суббота, 21 Июнь, 2014 20:56 
Модератор
Аватара пользователя

Зарегистрирован: Понедельник, 14 Ноябрь, 2005 18:39
Сообщения: 9141
Откуда: Россия, Орёл
При чём тут сам язык SQL.

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

Функциональность очень важная.
В режиме отдельной отправки на СУБД каждого INSERT-а с ожиданием ответа (а по-другому не получится взаимодействовать с базой) ты хорошо если 500 запросов в секунду прогонишь. А то и 200.

А у меня есть объект "результат измерений". Он содержит N параметров (N от 5 до 15 в зависимости от аппарата). Т.е. для добавления ОДНОГО объекта в базу нужно 6-16 INSERT-ов (т.е. параметры хранятся не поколоночно, а по трём таблицам int_params, real_params, string_params).
А если в пакетном режиме добавляется 500 таких результатов измерений (в конце дня пошёл экспорт с аппарата)?

Это под 10000 INSERT-ов...


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Mysql
СообщениеДобавлено: Воскресенье, 22 Июнь, 2014 09:50 
Администратор

Зарегистрирован: Вторник, 15 Ноябрь, 2005 01:14
Сообщения: 4302
Откуда: Россия, Орёл
Это немного. Более того, в одном INSERT можно передвать много записей (VALUES).


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Mysql
СообщениеДобавлено: Воскресенье, 22 Июнь, 2014 09:59 
Модератор
Аватара пользователя

Зарегистрирован: Понедельник, 14 Ноябрь, 2005 18:39
Сообщения: 9141
Откуда: Россия, Орёл
VALUES не спасает, если идёт INSERT в одну таблицу, затем несколько ISERTов в разные подчинённые, с использованием в них LAST_INSERT_ID() для связывания с только что добавленной записью в главную.

Как это немного, если чисто физически на TCP/IP в режиме "запрос - ожидание ответа - следующий запрос" ты много за секунду не прогонишь из-за латентности (мы же ещё на своих даже протоколах налетали на это, кажется, упирались в порядка нескольких сотен запрос-ответов в секунду).

Таким образом, выполнение в индивидуальном режиме 10 тысяч INSERTов затянется на пол-минуты точно.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Mysql
СообщениеДобавлено: Воскресенье, 22 Июнь, 2014 10:03 
Администратор

Зарегистрирован: Вторник, 15 Ноябрь, 2005 01:14
Сообщения: 4302
Откуда: Россия, Орёл
Это нормально. Кстати, сделай два варианта и посмотри, сильно ли будет отличается скорость. Нужен эксперимент.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Mysql
СообщениеДобавлено: Воскресенье, 22 Июнь, 2014 13:15 
Аватара пользователя

Зарегистрирован: Четверг, 08 Октябрь, 2009 15:00
Сообщения: 2367
Илья Ермаков писал(а):
А у меня есть объект "результат измерений". Он содержит N параметров (N от 5 до 15 в зависимости от аппарата). Т.е. для добавления ОДНОГО объекта в базу нужно 6-16 INSERT-ов (т.е. параметры хранятся не поколоночно, а по трём таблицам int_params, real_params, string_params).
А если в пакетном режиме добавляется 500 таких результатов измерений (в конце дня пошёл экспорт с аппарата)?

Это под 10000 INSERT-ов...

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


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Mysql
СообщениеДобавлено: Воскресенье, 22 Июнь, 2014 17:56 
Модератор
Аватара пользователя

Зарегистрирован: Понедельник, 14 Ноябрь, 2005 18:39
Сообщения: 9141
Откуда: Россия, Орёл
На самом деле, мы занимаемся тем, чем занимается любой ORM (Object-Relation Mapper...)
Неплохо некоторые идеи описаны у Усова (http://alexus.ru/russian/articles/dbms/oop_rm/index.htm).

Контекст проекта: небольшой заказ на сбор данных с трёх медицинских анализаторов.
Делают мои студенты, архитектуру-каркас, естественно, пришлось с ними вместе выстроить.

Проектировалась не реляционная БД, проектировалась объектная модель - и ровно нужные функции хранения и выборки объектов. А потом уже это проецировалось на реляционку (а можно без изменения приложения реализовать на чём угодно). Я бы охотнее взял NoSQL - Mongo ту же самую (у нас она применяется, но не из ББ). Но ввиду отсутствия драйвера....

Если интересно, выглядит примерно так модель и хранение.

Это объектная модель:
Код:
DEFINITION HemoData;

   IMPORT Dates;

   CONST
      maxParamCount = 64;

   TYPE
      PersonalCode = ARRAY 64 OF SHORTCHAR;

      DateTime = RECORD
         date: Dates.Date;
         time: Dates.Time
      END;

      Result = POINTER TO LIMITED RECORD (* Result почти неизменен, создаётся и "накачивается" данными однократно - при получении с анализатора, потом отправляется в базу. После считывания из базы возможно только одно изменение - FixPersonalCode. *)
         readOnly-: BOOLEAN;
         dbCode-: INTEGER;
         personalCode-: PersonalCode;
         analyzerType-: INTEGER;
         analyzeTime-, registerTime-: DateTime;
         values-: Value;
         (r: Result) AddInt (param, x: INTEGER), NEW;
         (r: Result) AddReal (param: INTEGER; x: REAL), NEW;
         (r: Result) AddString (param: INTEGER; IN s: ARRAY OF CHAR), NEW;
         (r: Result) Lock, NEW; (* Переводит объект в режим readOnly, после добавления всех параметров *)
         (r: Result) FixPersonalCode (IN newCode: ARRAY OF SHORTCHAR), NEW; (* Единственная операция, изменяющая уже существующий в базе результат *)
         (r: Result) Param (param: INTEGER): Value, NEW
      END;

      Value = POINTER TO ABSTRACT RECORD
         next-: Value;
         param-: INTEGER
      END;

      IntValue = POINTER TO LIMITED RECORD (Value)
         x-: INTEGER
      END;

      RealValue = POINTER TO LIMITED RECORD (Value)
         x-: REAL
      END;

      StringValue = POINTER TO LIMITED RECORD (Value)
         x-: POINTER TO ARRAY OF CHAR
      END;

   VAR
      nullTime-: DateTime;

   PROCEDURE NewResult (dbCode: INTEGER; IN personalCode: ARRAY OF SHORTCHAR; analyzerType: INTEGER; IN analyzeTime, registerTime: DateTime): Result;

END HemoData.


А это хранилище:
Код:
DEFINITION HemoDB;
   IMPORT HemoData, Dates, HemoCollections;

   CONST
      compareAnalyzeDate = 2; compareAnalyzerType = 1; comparePersonalCode = 0; compareRegisterDate = 3;

   TYPE
      Criteria = RECORD
         compare: SET;
         personalCode: HemoData.PersonalCode;
         analyzerType: INTEGER;
         analyzeDates, registerDates: RECORD
            from, to: Dates.Date
         END
      END;

   VAR
      connected-: BOOLEAN;

   PROCEDURE Connect;
   PROCEDURE Close;
   PROCEDURE RegisterResults (results: HemoCollections.Collection);
   PROCEDURE UpdatePersonalCodes (results: HemoCollections.Collection);
   PROCEDURE Select (IN criteria: Criteria): HemoCollections.Collection;

END HemoDB.



База имеет следующий вид:
Код:
CREATE TABLE results (
   id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
   personalCode VARCHAR(255) NOT NULL,
   analyzerType INT UNSIGNED NOT NULL,
   analyzeDate DATE NOT NULL,
   analyzeTime TIME NOT NULL,
   registerDate DATE NOT NULL,
   registerTime TIME NOT NULL
);

CREATE TABLE real_values (
   result_id INT UNSIGNED NOT NULL,
   param INT UNSIGNED NOT NULL,
   value REAL NOT NULL,
   FOREIGN KEY (result_id) REFERENCES results(id),
   UNIQUE(result_id, param)
);

CREATE TABLE string_values (
   result_id INT UNSIGNED NOT NULL,
   param INT UNSIGNED NOT NULL,
   value VARCHAR(255) NOT NULL,
   FOREIGN KEY (result_id) REFERENCES results(id),
   UNIQUE(result_id, param)
);

CREATE TABLE int_values (
   result_id INT UNSIGNED NOT NULL,
   param INT UNSIGNED NOT NULL ,
   value INT UNSIGNED NOT NULL,
   FOREIGN KEY (result_id) REFERENCES results(id),
   UNIQUE(result_id, param)
);

Плюс, конечно, индексы.


Таким образом, при реализации на базе SQL RegisterResults продуцирует последовательность INSERT INTO results ...; INSERT INTO xx_values VALUES (LAST_INSERT_ID()).........

Select продуцирует UNION SELECT следующего вида (где условие WHERE приходится трижды помещать в каждый SELECT):
Код:
SELECT id, personalCode, analyzerType, analyzeDate, analyzeTime, registerDate, registerTime, param, 1 AS param_type, value AS int_value, NULL AS real_value, NULL AS string_value FROM results, int_values WHERE result_id = id " + where +
"UNION SELECT id, personalCode, analyzerType, analyzeDate, analyzeTime, registerDate, registerTime, param, 2 AS param_type, NULL AS int_value, NULL AS real_value, value AS string_value FROM results, string_values WHERE result_id = id " + where +
"UNION SELECT id, personalCode, analyzerType, registerDate, registerTime, registerDate, registerTime, param, 3 AS param_type, NULL AS int_value, value AS real_value, NULL AS string_value FROM results, real_values WHERE result_id = id ORDER BY id";


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Mysql
СообщениеДобавлено: Воскресенье, 22 Июнь, 2014 18:15 
Модератор
Аватара пользователя

Зарегистрирован: Понедельник, 14 Ноябрь, 2005 18:39
Сообщения: 9141
Откуда: Россия, Орёл
Ну а теперь убедительный тест преимущества пакетных INSERT.

Процедура Insert1000 засунет в базу 1000 объектов (с 5 параметрами каждый, т.е. 6000 INSERT) пакетным запросом.

Процедура RegisterBySeparateRequests каждый объект засовывает отдельным обращением к базе (т.е. 1000 запросов к СУБД, в каждом по 6 INSERT).

Код:
   PROCEDURE Register1000*;
      VAR results: Collections.Collection;
         res: Data.Result;
         i: INTEGER;
         t: LONGINT;
   BEGIN
      res := NewResult();
      results := Collections.dir.New();
      FOR i := 0 TO 1000 DO
         results.InsertLast(res);
      END;
      DB.RegisterResults(results)
   END Register1000;

   PROCEDURE RegisterBySeparateRequests*;
      VAR results: Collections.Collection;
         res: Data.Result;
         i: INTEGER;
         t: LONGINT;
   BEGIN
      results := Collections.dir.New();
      res := NewResult();
      results.InsertLast(res);
      FOR i := 0 TO 1000 DO
         DB.RegisterResults(results)
      END
   END RegisterBySeparateRequests;


Пакетный режим, добавление 1000 объектов: 952 msec
Отдельный режим, добавление 1000 объектов с 1000 обращений к СУБД: 37152 msec

Тест делался на localhost, по сети сейчас не могу, думаю, что разрыв будет ещё существеннее.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Mysql
СообщениеДобавлено: Воскресенье, 22 Июнь, 2014 20:15 
Администратор

Зарегистрирован: Вторник, 15 Ноябрь, 2005 01:14
Сообщения: 4302
Откуда: Россия, Орёл
Это очевидно и без теста. Я просил сделать сравнение между "Пакетным INSERT" и INSERT ... VALUES.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Mysql
СообщениеДобавлено: Воскресенье, 22 Июнь, 2014 21:37 
Модератор
Аватара пользователя

Зарегистрирован: Понедельник, 14 Ноябрь, 2005 18:39
Сообщения: 9141
Откуда: Россия, Орёл
Так толку тестировать INSERT VALUES, если он невозможен для данной задачи.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Mysql
СообщениеДобавлено: Понедельник, 23 Июнь, 2014 09:25 

Зарегистрирован: Пятница, 20 Июль, 2007 17:26
Сообщения: 693
Откуда: Псков
Илья Ермаков писал(а):
Контекст проекта: небольшой заказ на сбор данных с трёх медицинских анализаторов.
Делают мои студенты ...

оффтоп:
может быть полезно студентам для представления о том, во что вырастает "небольшой заказ на сбор данных с трёх медицинских анализаторов"
у "серьёзных пацанов" :)
http://intersystems.ru/trakcarelab/


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Mysql
СообщениеДобавлено: Понедельник, 23 Июнь, 2014 13:31 

Зарегистрирован: Вторник, 30 Июнь, 2009 14:58
Сообщения: 1549
Илья, так сделайте в одну таблицу если нужна производительность. Вам места жалко? :)


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Mysql
СообщениеДобавлено: Понедельник, 23 Июнь, 2014 18:05 
Модератор
Аватара пользователя

Зарегистрирован: Понедельник, 14 Ноябрь, 2005 18:39
Сообщения: 9141
Откуда: Россия, Орёл
Хотелось отработать наиболее прямой, универсальный способ рукодельного ORM.

Всё в одну таблицу - это уже оптимизация под частный случай...

По производительности - там с одного аппарата данные идут сразу после каждого анализа - и никаких узких мест быть не может.
А вот с двух других сгружаться будут в пакетном режиме.
И не хотелось иметь тормоз на этом пакетном режиме.

Кстати, в отношении самого главного и сложного из трёх аппаратов (HEMOLUX-19) сегодня ребята оттестировали - работает системка...


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Mysql
СообщениеДобавлено: Среда, 25 Июнь, 2014 09:18 

Зарегистрирован: Понедельник, 30 Июль, 2007 10:53
Сообщения: 1538
Откуда: Беларусь, Минск
А предопределённые выражения той же производительности не добавили бы?

Это вместо точки с запятой, которая, между прочим, сделала возможным это.
Или вообще использовать хранимые процедуры.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Mysql
СообщениеДобавлено: Среда, 25 Июнь, 2014 10:58 
Модератор
Аватара пользователя

Зарегистрирован: Понедельник, 14 Ноябрь, 2005 18:39
Сообщения: 9141
Откуда: Россия, Орёл
А как скармливать хранимой процедуре массу записей для добавления?

Ну и уже идёт завязка на базоспецифический синтаксис процедур.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Mysql
СообщениеДобавлено: Четверг, 26 Июнь, 2014 17:26 

Зарегистрирован: Понедельник, 30 Июль, 2007 10:53
Сообщения: 1538
Откуда: Беларусь, Минск
Где-то видел анализ обработки запроса во времени для MySQL. Там говорилось, что время обработки одного запроса в целом можно поделить на 3 части: передача данных, разбор строки и поиск. Эти три части почти одинаковые.

>А как скармливать хранимой процедуре массу записей для добавления?
Вы, добавив обработку точки с запятой, сэкономили на времени передачи. Я же предлагаю вместо этого сэкономить на разборе строки запроса.

>идёт завязка на базоспецифический синтаксис процедур.
Вы про синтаксис объявления или вызова? Я не уверен, но мне кажется, что вызов процедуры одинаков для всех (или большинства) СУБД. А добавление процедур можно сделать и руками.

В MySQL нет возможности делать процедуры с переменным числом параметров или передавать список в качестве параметра, но есть обходной путь - использовать вместо списков строки с разделителем, а внутри процедуры разбивать строки на подстроки стандартными SQL-функциями.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Mysql
СообщениеДобавлено: Четверг, 26 Июнь, 2014 18:10 
Модератор
Аватара пользователя

Зарегистрирован: Понедельник, 14 Ноябрь, 2005 18:39
Сообщения: 9141
Откуда: Россия, Орёл
Valery Solovey писал(а):
Где-то видел анализ обработки запроса во времени для MySQL. Там говорилось, что время обработки одного запроса в целом можно поделить на 3 части: передача данных, разбор строки и поиск. Эти три части почти одинаковые.


Тут вступает в силу ещё одна фаза: латентность запроса. Я как раз с этого и начал в первом сообщении.
Передать данные потоком в одну сторону можно очень быстро, а вот обмен "запрос-ответ" дорого обходится. На стандартном стеке оборудования и протоколов больше нескольких сотен взаимообменов запросом-ответом в секунду Вы вряд ли получите.

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


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Mysql
СообщениеДобавлено: Пятница, 27 Июнь, 2014 09:32 

Зарегистрирован: Понедельник, 30 Июль, 2007 10:53
Сообщения: 1538
Откуда: Беларусь, Минск
Илья Ермаков писал(а):
Тут вступает в силу ещё одна фаза: латентность запроса. Я как раз с этого и начал в первом сообщении.
Передать данные потоком в одну сторону можно очень быстро, а вот обмен "запрос-ответ" дорого обходится. На стандартном стеке оборудования и протоколов больше нескольких сотен взаимообменов запросом-ответом в секунду Вы вряд ли получите.

Про латентность я говорил, это фаза передачи данных.

Я тут совсем забыл... Работа с БД идёт в блокирующем режиме, да? То есть, несколько соединений открывать бессмысленно, чтобы отправлять запросы параллельно?


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Mysql
СообщениеДобавлено: Пятница, 27 Июнь, 2014 13:42 
Модератор
Аватара пользователя

Зарегистрирован: Понедельник, 14 Ноябрь, 2005 18:39
Сообщения: 9141
Откуда: Россия, Орёл
Угу.
Драйвер ББ Ивана блокирующий.

Хотя сам интерфейс подсистемы Sql допускает асинхронность...
Но это уже какие-то навороты пошли.

Ну, давайте прикинем - если просадка по быстродействию при последовательных запросов порядка 30 раз, что нам - открывать 30 соединений к базе параллельно? Ну, можно, но как-то...


Вернуться к началу
 Профиль  
 
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 39 ]  На страницу Пред.  1, 2

Часовой пояс: UTC + 3 часа


Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 1


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
cron
Вся информация, размещаемая участниками на конференции (тексты сообщений, вложения и пр.) © 2005-2019, участники конференции «OberonCore», если специально не оговорено иное.
Администрация не несет ответственности за мнения, стиль и достоверность высказываний участников, равно как и за безопасность материалов, предоставляемых участниками во вложениях.
Без разрешения участников и ссылки на конференцию «OberonCore» любое воспроизведение и/или копирование высказываний полностью и/или по частям запрещено.
Powered by phpBB® Forum Software © phpBB Group
Русская поддержка phpBB