Лучшая практика вставки и запроса данных из памяти

#wcf #in-memory-database

#wcf #база данных в памяти

Вопрос:

У нас есть приложение, которое принимает данные в реальном времени и вставляет их в базу данных. он подключен к сети 4,5 часа в день. Мы вставляем данные посекундно в 17 таблиц. Пользователь в любое время может запросить любую таблицу для получения последних вторых данных и некоторой записи в истории…

Обработка потока и вставка выполняются с помощью консольного приложения C #…

Обработка пользовательских запросов осуществляется через службу WCF…

Мы выяснили, что вставка является нашим узким местом; на это уходит большая часть времени. Мы потратили много времени, пытаясь доработать таблицы и показатели, но результаты не были удовлетворительными

Предполагая, что у нас достаточно памяти, какова наилучшая практика для вставки данных в память вместо наличия базы данных. В настоящее время мы используем таблицы данных, которые обновляются и вставляются каждую секунду. Наш коллега предложил другую службу WCF вместо базы данных между обработчиком каналов и обработчиком пользовательских запросов WCF. Предполагается, что средний уровень WCF основан на TCP и хранит данные в своей собственной памяти. Можно сказать, что обработчик канала мог бы обрабатывать запросы пользователей вместо того, чтобы иметь средний уровень между двумя процессами, но мы хотим разделить вещи, поэтому, если произойдет сбой обработчика канала, мы хотим по-прежнему иметь возможность предоставлять пользователю текущие записи

Мы ограничены во времени, и мы хотим переместить все в память за короткий период. Является ли плохим использование WCF в середине двух процессов? Я знаю, что запросы добавляют некоторые накладные расходы, но все эти 3 процесса (обработчик каналов, база данных в памяти (WCF), обработчик пользовательских запросов (WCF) будут находиться на одном компьютере, и пропускная способность не будет такой уж большой проблемой.

Пожалуйста, помогите!

Комментарии:

1. Действительно хороший вопрос.

Ответ №1:

Я бы рассмотрел возможность создания кэша данных (такого, чтобы вы также могли уменьшить количество выборок в базе данных) и аннулировать данные в кэше после их записи в базу данных. Таким образом, вы можете выполнять групповые вызовы для выполнения вставки большего размера вместо множества меньших, но при этом сохранять данные в памяти таким образом, чтобы читатели могли их прочитать. На самом деле, если вы знаете, когда данные устаревают, вы можете не читать базу данных полностью и использовать ее только как резервное хранилище — таким образом, производительность базы данных повлияет только на то, насколько большим станет ваш кэш.

Аннулирование данных в кэше будет зависеть либо от того, записаны ли они в базу данных, либо от того, устарели ли они, что всегда происходит последним, а не первым.

Уровень кэша не обязательно должен быть сложным, однако он должен быть многопоточным для размещения данных, а также сохранения их в фоновом режиме. Этот уровень должен располагаться сразу за службой WCF, средой подключения, и службу WCF следует улучшить, чтобы она содержала логику консольного приложения идею пакетной обработки. Тогда консольное приложение может просто подключиться к WCF и выдать ему результаты.

Обновление: единственное, что еще можно сказать, это инвестировать в профилировщик, чтобы увидеть, не вводите ли вы какие-либо проблемы с производительностью в код, которые маскируются. Кроме того, профилируйте свою базу данных. Вы упомянули, что вам нужны быстрые вставки и выборки — к сожалению, они обычно противоречат друг другу…

Комментарии:

1. Спасибо за ответ. Данные на самом деле не устаревают, поскольку каждая запись может быть выбрана в любое время (пользователь может указать вторую «запись», которую он / она хочет). Ваше решение по-прежнему предлагает вставлять в базу данных, хотя и реже, путем создания кэша, но мне интересно, собираемся ли мы по-прежнему выбирать из базы данных (если данные не в кэше, что возможно, учитывая, что выборки являются полностью случайными для исторических данных), в то время как по совпадению вставляется огромная таблица, не приведет ли это к тайм-аутам выбора? Разве мы не можем просто поместить все в память?

2. Это действительно зависит — вставки каждую секунду в течение 4,5 часов могут составлять много данных? Ваша проблема заключается в производительности вставки, которую можно решить другими способами. Что вы могли бы сделать, так это удалить все индексы, таким образом, адаптируя таблицу к производительности вставки и понеся затраты на выбор, возможно, используя кэш выбора для хранения большего количества этого в памяти.

3. Конечно, использование встроенной памяти — это возможный путь, но память также энергозависима — отключите питание, и все это исчезнет.

4. Удаление индексов позволило нам повысить производительность, а также удалить первичные ключи. Проблема здесь в том, что мы хотим быстрой вставки И выбора. Ожидания производительности в нашей области фондового рынка довольно высоки

5. Тогда я бы предложил промежуточный подход — попробуйте систему распределенного кэша (memcache, Velocity), которая обеспечивает быстрый доступ по сети, но поведение, подобное узлу, при котором один элемент в кэше копируется более чем на один сервер, практически полностью устраняя риск потери текущих данных. По-прежнему сохраняйте это в базе данных, но также помещайте все данные в кэш — единственная метрика, которую остается измерить, — это время от кэша до базы данных и то, сколько данных в кэше не сохраняется в любой момент времени.

Ответ №2:

Какую базу данных вы используете? В MySQL есть память механизма хранения, которая, казалось бы, подходит для такого рода вещей.

Комментарии:

1. Мы используем базу данных SQL. Microsoft SQL server 2008

Ответ №3:

Используете ли вы DataTable с DataAdapter? Если это так, я бы рекомендовал вам полностью удалить их. Вставляйте свои записи напрямую, используя DbCommand. Когда пользователи запрашивают отчеты, считывайте данные с помощью DataReader или заполняйте объекты DataTable с помощью DataTable.Загрузка (IDataReader).

Хранение данных в памяти сопряжено с риском потери данных в случае сбоев или сбоев питания.

Комментарии:

1. Мы создаем соединение SqlTransaction и используем его для вставки, перебирая DataTable с помощью SqlBulkCopy. Нам нужна транзакция для того, чтобы обратить вспять эффект возможных сбоев