2015-04-10 3 views
0

У меня есть некоторые данные (приблизительно 5 миллионов единиц в 1500 таблицах, 10 ГБ) в лазурных таблицах. Сущности могут быть большими и содержать некоторые серийные двоичные данные в формате protobuf.Azure Table Storage QueryAll(), ImproveThroughput

Я должен обработать их все и преобразовать в другую структуру. Эта обработка не является потокобезопасной. Я также обрабатываю некоторые данные из набора реплик mongodb, используя тот же код (mongodb размещен в другом центре обработки данных).

Для целей отладки я регистрирую пропускную способность и понял, что он очень низок. С mongodb я имею пропускную способность 5000 пунктов/сек, с лазурным столом хранения только 30 пунктов в секунду.

Для повышения производительности, я пытаюсь использовать TPL поток данных, но это не помогает:

public async Task QueryAllAsync(Action<StoredConnectionSetModel> handler) 
{ 
    List<CloudTable> tables = await QueryAllTablesAsync(companies, minDate); 

    ActionBlock<StoredConnectionSetModel> handlerBlock = new ActionBlock<StoredConnectionSetModel>(handler, new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = 1 }); 

    ActionBlock<CloudTable> downloaderBlock = new ActionBlock<CloudTable>(x => QueryTableAsync(x, s => handlerBlock.Post(s), completed), new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = 20 }); 

    foreach (CloudTable table in tables) 
    { 
     downloaderBlock.Post(table); 
    } 
} 

private static async Task QueryTableAsync(CloudTable table, Action<StoredConnectionSetModel> handler) 
{ 
    TableQuery<AzureTableEntity<StoredConnectionSetModel>> query = new TableQuery<AzureTableEntity<StoredConnectionSetModel>>(); 

    TableContinuationToken token = null; 
    do 
    { 
     TableQuerySegment<AzureTableEntity<StoredConnectionSetModel>> segment = await table.ExecuteQuerySegmentedAsync<AzureTableEntity<StoredConnectionSetModel>>(query, token); 

     foreach (var entity in segment.Results) 
     { 
      handler(entity.Entity); 
     } 

     token = segment.ContinuationToken; 
    } 
    while (token != null) 
} 

Я запустить процесс пакетной обработки на моей локальной машине (с подключением 100Mbit) и в лазури (как работник роли) и очень странно, что пропускная способность моей машины выше (100 единиц/сек), чем на лазури. Я достигаю максимальной емкости интернет-соединения на местном уровне, но на роль рабочего не должно быть этого ограничения на 100 мбайт. Надеюсь.

Как увеличить пропускную способность? У меня нет идей, что здесь происходит не так.


EDIT: Я понял, что ошибся с 30items в секунду. Он часто выше (100/сек), в зависимости от размера предметов, которые я предполагаю. В соответствии с документацией (http://azure.microsoft.com/en-us/documentation/articles/storage-performance-checklist/#subheading10) существует предел:

Предел масштабируемости для доступа к таблицам составляет до 20 000 объектов (1 КБ каждая) в секунду для учетной записи. Это всего лишь 19 МБ/с, что не так впечатляет, если вы помните, что есть также обычные запросы от производственной системы). Вероятно, я тестирую его, чтобы использовать несколько учетных записей.


EDIT # 2: Я сделал два одиночных испытаний, начиная со списком 500 ключей [1 ... 500] (псевдокод)

Test # 1 Старый подход (Таблица 1)

foreach (key1 in keys) 
    foreach (key2 in keys) 
     insert new Entity { paritionkey = key1, rowKey = key2 } 

Test # 2 Новый подход (Таблица 2)

numpartitions = 100 
foreach (key1 in keys) 
    foreach (key2 in keys) 
     insert new Entity { paritionkey = (key1 + key2).GetHashCode() % numParitions, rowKey = key1 + key2 } 

Каждый объект получает еще одно свойство с 10KB случайных текстовых данных.

Тогда я сделал тесты запросов, в первом случае я просто запросить все объекты из таблицы 1, в одном потоке (последовательном)

В следующем тесте я создаю на задачу для каждого PartitionKey и запросить все объекты из таблицы 2 (параллельно). Я знаю, что тест не так уж хорош, потому что в моей производственной среде у меня гораздо больше разделов, чем только 500 на таблицу, но это не имеет значения. По крайней мере, вторая попытка должна выполняться хорошо.

Не имеет значения. Моя максимальная пропускная способность составляет 600 сущ./С, в большинстве случаев от 200 до 400. В документации говорится, что я могу запросить 20 000 единиц/сек (по 1 КБ каждый), поэтому я должен получить как минимум 1500 или около того в среднем, я думаю. Я тестировал его на машине с подключением к Интернету на 500 Мбит, и я достиг всего около 30 мбит, так что это не должно быть проблемой.

+0

Вы проверили - Контрольный список масштабируемости производительности и хранения - http://azure.microsoft.com/en-us/documentation/articles/storage-performance-checklist/ Если нет, пожалуйста, посмотрите –

+0

«Чтобы улучшить производительность I попробуйте использовать поток данных TPL, но он не помогает «Это говорит мне, что вы не знаете, почему это происходит медленно, и вы попытались случайное изменение, чтобы оно ускорилось. Нехороший путь. Узнайте, почему это происходит медленно. Выключена ли сеть локально? Является ли CPU 100% занятым (даже на одном ядре)? – usr

+0

@usr Я думаю, что это неправда. Как я уже упоминал выше, сеть локализована локально, процессор находится на уровне 20% (на всех ядрах), поэтому, похоже, проблема заключается в том, чтобы получить данные достаточно быстро. Процесс импорта из mongodb показывает, что есть пространство для увеличения пропускной способности и ожидание процессора. Я использую поток данных для параллельного выполнения нескольких запросов и для синхронизации операций обработки данных. – SebastianStehle

ответ

Смежные вопросы