Маркет+ и СУБД
Оптимизация. Оценка производительности.
Вступление.
Каждый, кто хоть раз сталкивался с программный комплекс Маркет+, наверняка слышал или читал о возможности построения на его основе сложных иерархических систем с централизованным управлением. Не будем вдаваться в подробности такой архитектуры, а также в ее достоинства и недостатки, т.к. это не является целью настоящей статьи. Отметим лишь, что венцом такой системы всегда является так называемый «корневой сервер данных». То есть, весь поток данных, собранный по всему дереву системы попадает в узкую точку корневого сервера, который, в конечном счете, и определяет производительность всей системы.
В статье, посвященной исследованию производительности кассы, проведя ряд экспериментов, мы пришли к выводу, что при размерах справочников (равно как и исходящих таблиц) не более 100 000 (ста тысяч), производительность на всех поддерживаемых СУБД примерно равна (отличия в пределах 5%, т.е. соизмеримы с величиной погрешности измерений), и практически не зависит от параметров настройки канала (размера пакетов, таймаутов и т.д.), а следовательно, никакой оптимизации не требуется. Однако по мере увеличения размера справочников от 100 000 до 1 000 000 (миллиона) эффективность параметров настройки канала растет, становясь необходимой при работе со справочниками больше 1000 000. Аналогично дело обстоит и с настройкой СУБД.
Для облегчения вами выбора СУБД, дать рекомендации по настройке параметров канала и оценить производительность сервера данных, нами был произведен ряд исследований, которым собственно и посвящена эта статья.
Основные исследуемые вопросы.
1.) Сервер данных Маркет+ может работать с несколькими СУБД:
В силу ограничений на максимальный размер файла БД, FireBird нельзя рассматривать как СУБД для больших систем, поэтому исследования для него не производились. Однако хочу напомнить, что сравнение MSSQL и FireBird на объемах справочников до 1 000 000 (1 млн.) показали, что отличие в производительности между ними на уровне 5%, а это не так существенно. Сравнение же MSSQL и Oracle может оказаться интересным для тех, кто подходит к задаче не предубежденно, и не имея никаких побочных факторов, влияющих на его выбор. Какая из СУБД будет предпочтительней с точки зрения сервера данных Маркет+?
2.) Исследования, проводимые нами 4 года назад, показали, что ограничение производительности наступает за счет процессора и памяти. На основании этого были даны рекомендации изменять количество одновременно обрабатываемых потоков таким образом, чтобы загрузка памяти и процессора не превышала 80-90% от максимальной. Такой подход обеспечивал максимальную производительность сервера. С тех пор сменилось несколько поколений процессоров, магические 2 Гб памяти стали обыденными... Актуальны ли теперь эти рекомендации? Что теперь ограничивает производительность сервера данных? Как добиться от него максимальной производительности?
3.) Работа сервера данных состоит из трех основных задач:
- получение данных от клиентов,
- передача данных в транзитную базу,
- очистка устаревших данных.
Очевидно, что при оценке производительности сервера данных следует учитывать выполнение всех вышеперечисленных задач, т.к. только такой подход позволит оценить «долговременную» производительность. В самом деле, отказ, например от очистки (в этот момент сервер данных приостанавливает выполнение остальных задач), временно повысит среднесуточную производительность системы, но впоследствии объем данных будет расти и производительность будет снижаться, а потом система и вовсе остановится, т.к. дисковое пространство под БД закончится. Не трудно заметить, что к похожим последствиям приведет исключение любой из трех задач сервера. Итак, какова же максимальная производительность сервера данных, настроенного оптимально?
Описание стенда.
Сформулировав основные интересующие нас вопросы, прежде чем привести результаты исследований, опишем испытательный стенд. Его архитектура выглядит следующим образом:

В качестве клиентов выступают сервера данных, данные для которых генерируются специальным тестовым приложением. Последнее создает в базах клиентских серверов полные чеки по 7 номенклатурных позиций, 2 записи 1-й и 2-й тэг, а так же 32 записи SALESEXT и 9 записей в SYSLOG, что соответствует среднестатистическому чеку. В качестве настройки тестовое приложение получает паузу между такими чеками в миллисекундах. Таким образом, есть возможность управлять скоростью генерации чеков. СУБД клиентов для наших экспериментов значения не имеет, поэтому наш выбор пал на MSSQL.
Корневой сервер данных и транзитная база данных (ТБД) находятся на разных физических серверах. Во всех случаях используются одни и те же сервера (Intel Core 2 Duo E6600, 2.40 GHz (9 x 267), 2гБ памяти) и операционные системы на них. СУБД сервера и СУБД транзитной базы всегда одинаковы (т.е. и там и там MSSQL или Oracle при соответствующих экспериментах).
Все эксперименты проводятся последовательно, т.е. сначала для одной СУБД, а затем на чистых базах для другой. Не используемая СУБД на момент испытаний остановлена, т.е. не потребляет ресурсов.
Обе СУБД установлены «по умолчанию», без каких бы то ни было дополнительных настроек. Файлы логов и данных находятся на системном диске.
Испытания и их результаты:
1.) Исследуем требовательность к ЦП для разных СУБД. Для этого запускаем на всех клиентах генерацию продаж с паузой между чеками (0,033*[кол. клиентов]) секунд, и подбираем количество подключений к БД таким образом, чтобы средняя загрузка процессора была примерно 80% (если при использовании всех доступных клиентов цель не достигнута, то указываем для данной СУБД количество клиентов и загрузку процессора).
Результаты измерений заносим в таблицу:
|
СУБД
|
Количество подключений, соотв. 80% загрузки процессора.
|
|
MSSQL
|
22, 50%
|
|
Oracle
|
22, 70%
|
Таким образом, видим, что процессор более не является узким местом системы. Во многом этому способствует многоядерность процессоров, т.к. практически устраняет конкуренцию между сервером данных и его СУБД.
2.) Определяем оптимальное количество одновременно-работающих клиентов. Для этого останавливаем DATAPUMP и принимаем с клиентов не менее 10 000 000 (10 млн.) записей SALES (это необходимо, чтобы нивелировать падение производительности по мере увеличения объема данных в базе, в ходе эксперимента). Далее включаем DATAPUMP и ставим клиентов в ожидание, а затем, по паре добавляем и измеряем скорость передачи по DATASYNC и по DATAPUMP в течение часа, и так для всех клиентов.
Результаты измерений заносим в таблицу (для каждой СУБД в отдельную):
MSSQL
|
Кол-во клиентов
|
Кол. в базе СД
(начало)
|
Кол. в транзитной БД
(начало)
|
Время начала
|
Кол. в базе СД
(конец)
|
Кол. в транзитной БД
(конец)
|
Время конца
|
Скорость СД (зап./мин.)
|
Скорость ТБД (зап./мин.)
|
|
2
|
10927615
|
0
|
15:35
|
11460293
|
697000
|
16:35
|
8878
|
11616
|
|
4
|
11460293
|
697000
|
16:36
|
12923293
|
1357000
|
17:36
|
24384
|
11000
|
|
6
|
12923293
|
1357000
|
10:10
|
15291293
|
1997000
|
11:10
|
39467
|
10666
|
|
8
|
15291293
|
1997000
|
11:13
|
17910293
|
2623000
|
12:13
|
43650
|
10433
|
|
10
|
17910293
|
2623000
|
12:15
|
20759293
|
3243000
|
13:15
|
47484
|
10333
|
|
12
|
20759293
|
3243000
|
13:30
|
23538293
|
3867000
|
14:30
|
46317
|
10400
|
|
14
|
23538293
|
3867000
|
14:36
|
26406392
|
4480000
|
15:36
|
47802
|
10216
|
|
16
|
26406392
|
4480000
|
15:40
|
28962327
|
5046000
|
16:40
|
42599
|
9433
|
|
18
|
28962327
|
5046000
|
16:43
|
31855327
|
5604000
|
17:43
|
48217
|
9300
|
|
20
|
31855327
|
5604000
|
10:33
|
34632723
|
6144000
|
11:33
|
46290
|
9000
|
|
22
|
34632723
|
6144000
|
11:36
|
37332723
|
6694000
|
12:36
|
45000
|
9166
|
Oracle
|
Кол-во клиентов
|
Кол. в базе СД
(начало)
|
Кол. в транзитной БД
(начало)
|
Время начала
|
Кол. в базе СД
(конец)
|
Кол. в транзитной БД
(конец)
|
Время конца
|
Скорость СД (зап./мин.)
|
Скорость ТБД (зап./мин.)
|
|
2
|
10355000
|
140000
|
10:30
|
11009722
|
422000
|
11:30
|
10912
|
4700
|
|
4
|
11009722
|
422000
|
11:30
|
11917429
|
678000
|
12:30
|
15128
|
4266
|
|
6
|
11917429
|
678000
|
12:30
|
13081854
|
914000
|
13:30
|
19407
|
3933
|
|
8
|
13081854
|
914000
|
13:30
|
13962906
|
1069000
|
14:30
|
14684
|
2583
|
|
10
|
13962906
|
1069000
|
14:30
|
14922580
|
1219000
|
15:30
|
15994
|
2500
|
|
12
|
14922580
|
1219000
|
15:30
|
15850765
|
1339000
|
16:30
|
15469
|
2000
|
|
14
|
15850765
|
1339000
|
16:30
|
16733000
|
1430000
|
17:30
|
14703
|
1516
|
|
16
|
16733000
|
1430000
|
20:15
|
17840040
|
1548000
|
21:15
|
18450
|
1966
|
|
18
|
17840040
|
1548000
|
21:15
|
18655066
|
1617000
|
22:15
|
13583
|
1150
|
|
20
|
18655066
|
1617000
|
22:15
|
19508211
|
1690000
|
23:15
|
14219
|
1216
|
|
22
|
19508211
|
1690000
|
23:15
|
20448000
|
1770000
|
00:15
|
15663
|
1333
|
На графике, ниже, представлены зависимости скоростей приема и передачи данных для MSSQL и Oracle от кол-ва одновременно-работающих клиентов.

Из графика следует, что при достижении скоростью приема данных некоторого значения, ее рост, с ростом числа клиентов, прекращается, а при черезмерном увеличении количества клиентов, появляется тенденция к плавному ее снижению. Кроме того, увеличение числа клиентов однозначно приводит к снижению скорости передачи данных в транзитную БД.
Выбор количества одновременно-работающих клиентов следует производить таким образом, чтобы получить оптимальное сочетание скоростей приема/передачи, т.е. максимальную совокупную производительность системы. Таким образом, для нашего стенда можно рекомендовать, для MSSQL количество клиентов в диаппазоне 10 - 14, а для Oracle 6 - 8.
Не следует принимать эти цифры как догму, т.к. в зависимости от аппаратной платформы, настройки СУБД и реального потока данных они могут меняться, однако следует помнить, что для любой системы существует определенное оптимальное кол-во одновременно обрабатываемых клиентов. К данным цифрам стоит отнестись как к опорным в вашем подборе оптимального значения, делая при этом поправку на конкретную аппаратную платформу.
3.) Определяем оптимальный размер пакета между клиентским сервером и корневым сервером. Для этого, устанавливаем оптимальное количество подключений к БД, соответствующее исследуемой СУБД. Измеряем объем переданных данных за час, для каждого из значений пакета (перед каждым измерением удаляем на клиентах все переданные записи):
- 1000,
- 5000,
- 10000,
- 20000.
Результаты измерений заносим в таблицу:
|
Размер пакета
|
Передано данных (за 60 мин. MSSQL)
|
Передано данных (за 60 мин. Oracle)
|
|
1000
|
2236000
|
1437848
|
|
5000
|
2635000
|
1630000
|
|
10000
|
3210000
|
1885000
|
|
20000
|
4114323
|
1940000
|
Рост производительности системы в зависимости от роста размера пакета вполне предсказуем, чем больше пакет, тем меньше запросов, и меньше времени на их выполнение. Однако, увеличение пакета выше 20000 приведет к большему потреблению памяти и росту времени выполнения запроса, что в свою очередь потребует увеличения таймаутов ожидания и сделает систему неудобной в эксплуатации. Кроме того, частые таймауты могут вызвать обратный эффект, т.е. падение производительности системы. Следует также помнить, что большие пакеты приемлемы только при стабильных каналах связи, а их эффективность проявляется в долгосрочной перспективе.
4.) Определяем производительность сервера данных. Для этого очищаем все базы. Выбираем оптимальные настройки на основании выше проведенных исследований. Указываем на корневом сервере период хранения данных - 1 сутки. Запускаем генерацию и передачу продаж. Периодически измеряем количество переданных данных.
Результаты измерений заносим в таблицу:
|
Кол. часов
|
Записей в СД/ТБД (MSSQL)
|
Записей в СД/ТБД (Oracle)
|
|
1
|
5100936/900000
|
3055203/600000 (1,5ч)
|
|
2
|
9114025/1740000
|
3674139/700000
|
|
5
|
16784218/4060000
|
8172456/1450588
|
|
10
|
24696426/7660000
|
13590000/2480588
|
|
24
|
43292506/19060000
|
25858344/5080588
|
|
48
|
66573134/36080000
|
Очистка не закончилась
|
Для MSSQL: после суточной очистки sales - 35 059 027 (очистка длилась 3 часа),
после двух суток salesext - 115 665 154, syslog - 35 654 263
Для Oracle: после суточной очистки sales - 22 571 121 (очистка длилась 1,25 суток),
после чего тест был остановлен.
Данные на момент остановки:
БД СД: sales - 23 793 009
salesext - 10 514 930
syslog - 6 598 868
ТБД: sales - 5 427 883
salesext - 5 010 000
syslog - 4 760 000
Выводы.
1.) Производительность сервера данных на MSSQL существенно выше, чем на Oracle (почти в 7 раз при транзитной передаче). Отметим, что сравнение касается не СУБД как таковых, а сервера данных, работающего на этих СУБД. Кроме того, СУБД, как отмечалось ранее, используются с настройками по умолчанию и файлами данных, находящихся на системном диске. Итак, вывод первый:
- если вы не являетесь специалистом в СУБД и хотите построить на основе Маркет+ высокопроизводительную систему, ваш выбор: MSSQL.
2.) Процессор более не является узким местом для сервера данных.
Ограничение производительности наступает из-за роста очереди дисковой системы. Для устранения данной проблемы, необходимо ограничивать кол-во одновременно обслуживаемых клиентов. В качестве опорного числа можно принять 12 (для Маркет+ 4.4 и ниже указывается кол-во подключений, которое считается как количество клиентов + 4=16) для MSSQL и 7 для Oracle. Очевидно, что с ростом производительности дисковой системы это число будет расти. В частности, к повышению производительности дисковой системы приводит вынос файлов лога и данных на отдельные физические носители. Размер пакета при стабильном канале связи следует указывать на уровне 20 000. Однако, в случае появления в логе сообщений о разрыве соединения с клиентом по таймауту, размер пакета должен быть снижен. Такие же действия рекомендуются при использовании нестабильных каналов связи. Для нагруженного сервера данных обязательно следует определять параметр «Максимальное число пакетов справочника», т.к. в противном случае, при достаточно интенсивном потоке данных сервер данных будет непрерывно передавать лишь одну исходящую таблицу.
3.) Производительность сервера данных на вышеописанном стенде, при полном цикле (прием + передача + очистка) составила 18 000 000 (18 млн.) записей продаж в сутки (при пропорциональной передаче SALESEXT и SYSLOG). Чтобы оценить много это или мало рассмотрим реальную и предельную ситуацию:
а.) Предположим, что кассир каждую секунду генерирует 1 номенклатурную позицию, очевидно, что за 24 часа кассир может сгенерировать 86400 записей в SALES. Это значение является верхним пределом производительности кассира. В таком случае сервер данных сможет обслужить 18000000/86400=208 касс, на которых работают такие безумные кассиры, и сохранять такой режим работы бесконечно долго (т.е. кассиры работают в таком режиме непрерывно, круглосуточно). Напомним, в цикле учтены временные затраты на очистку устаревших данных.
б.) Практические измерения показали, что магазин в городе - миллионнике величиною в 20 касс генерирует около 9 000 000 записей в месяц (это усредненные данные, полученные по нескольким крупным городам, от магазинов с разной специализацией и внутренним устройством). Таким образом, реальная касса генерирует в день 9000000/20/30=15000 записей SALES, а сервер данных может обслужить 18000000/15000=1200 реальных касс и сохранять такой режим работы бесконечно долго.
Заметим, что это не предел, т.к. существует еще резерв оптимизации БД и дисковой системы, что в совокупности, по нашим прогнозам даст прирост производительности на 30-50%.
Заключение.
В заключении отметим, что в ходе проведения испытаний были выполнены некоторые оптимизационные процедуры, в результате которых удалось поднять производительность сервера данных. Приводимые в этой статье данные касаются оптимизированного сервера. Такая версия Маркет+ будет доступна, только начиная с Маркет+4.5, причем для базы, созданной с нуля (а не полученной обновлением с предыдущих версий). При необходимости оптимизировать существующую БД, мы предлагаем обратиться в нашу службу поддержки.