Для меня определили задачу с загрузкой приблизительно 100 миллионов строк данных Azure устройство хранения данных Таблицы. Важная вещь, здесь являющаяся скоростью.
Процесс, который мы используем, загружает 10 000 строк с Azure устройство хранения данных Таблицы. Обработайте их в локальный экземпляр SQL-сервера. При обработке строк это удаляет 100 строк за один раз из таблицы Azure. Этот процесс является поточным, чтобы иметь 8 потоков, загружающих 10 000 строк за один раз.
Единственная проблема с этим - это согласно нашим вычислениям. Потребуется приблизительно 40 дней, чтобы загрузить и обработать эти приблизительно 100 миллионов строк, которые мы сохранили. Кто-либо знает более быстрый способ выполнить эту задачу?
Вопрос о стороне: Во время загрузки Azure процесса передаст обратно xml, который просто не имеет никаких данных. Это не передает ошибку обратно. Но это отправляет это:
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<feed xml:base="azure-url/" xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" xmlns="http://www.w3.org/2005/Atom">
<title type="text">CommandLogTable</title>
<id>azure-url/CommandLogTable</id>
<updated>2010-07-12T19:50:55Z</updated>
<link rel="self" title="CommandLogTable" href="CommandLogTable" />
</feed>
0
Кто-либо еще имеет эту проблему и имеет фиксацию для нее?
В дополнение к предложениям по отключению Nagling, есть очень хороший пост по улучшению производительности Azure Table Storage. На самом деле улучшение скорости десериализации ADO.NET обеспечило 10-кратное ускорение для Sqwarea (массовая многопользовательская онлайн-игра, построенная с использованием Lokad.Cloud framework).
Однако табличное хранилище может оказаться не лучшим решением для сценариев хранения огромных данных (более миллионов записей). Латентность здесь является решающим фактором. Чтобы обойти эту проблему, я успешно использую хранилища баз данных на основе файлов, где изменения делаются локально (без каких-либо сетевых задержек CLAP) и фиксируются в BLOB путем загрузки файла обратно (параллелизм и масштабирование здесь обеспечивались Lokad.CQRS App Engine для Windows Azure).
Вставка 10 миллионов записей в базу данных SQLite одновременно (в рамках транзакции, где каждая запись индексировалась по двум полям и имела произвольные бессхемные данные, сериализованные через ProtoBuf) заняла в среднем всего 200 секунд. Загрузка/выгрузка результирующего файла - в среднем около 15 секунд. Случайное чтение по индексу - мгновенно (при условии, что файл кэшируется в локальном хранилище и ETag совпадает).
Помимо предложений об ограничениях полосы пропускания, вы можете легко столкнуться с ограничениями учетной записи хранения, поскольку каждый раздел таблицы ограничен примерно 500 транзакциями в секунду.
Далее: развернута оптимизация (алгоритм Нэгла), которая действительно может замедлить выполнение небольших операций чтения (таких как чтение данных размером 1 КБ). Вот сообщение в блоге об отключении Nagling , которое потенциально может значительно ускорить чтение, особенно если вы работаете непосредственно в службе Azure без задержек в Интернете.
Что касается вашего побочного вопроса, я полагаю, что вы получаете "маркер продолжения". Если вы используете клиентскую библиотеку хранилища .NET, попробуйте добавить .AsTableServiceQuery() к вашему запросу.
Что касается вашего основного вопроса, веерное выполнение запроса - это лучшее, что вы можете сделать. Похоже, что вы обращаетесь к хранилищу с локальной машины (не в Windows Azure). Если это так, то я полагаю, что вы можете значительно ускорить процесс, развернув небольшую службу в Windows Azure, которая получает данные из табличного хранилища (намного быстрее, поскольку в центре обработки данных более высокая пропускная способность и меньшая задержка), а затем сжимает результаты и отправляет их обратно на локальную машину. В XML, который таблицы Windows Azure отправляют обратно, много накладных расходов, поэтому удаление этого и объединение строк, вероятно, сэкономит много времени передачи.
Скорее всего, вашим ограничивающим фактором является пропускная способность сети, а не обработка. Если это так, ваша единственная реальная надежда - расшириться: больше машин, выполняющих больше потоков для загрузки данных.
Кстати, разве Azure не предоставляет какой-то механизм «экспорта», который избавит от необходимости загружать все строки вручную?
Важным фактором здесь является то, как данные распределяются по разделам. Запрос, охватывающий границы раздела, будет возвращаться на каждой границе, требующей повторной отправки, даже если в рассматриваемом разделе 0 строк. ЕСЛИ данные 1 раздел = 1 строка, тогда они будут медленными, но вы можете увеличить количество потоков намного выше 8. Если данные находятся в n разделах = m строках, то приведенные ниже идеи должны ускорить вас.
Предполагая, что у вас есть несколько разделов и каждый с некоторым количеством строк, самым быстрым способом будет развернуть как можно больше потоков (если вы используете .Net, PLINQ или Parallel.ForEach (раздел) или QueueWorkItem ()) и попросите поток просканировать свой раздел на предмет всех строк, обработать, отправить в SQL и удалить перед возвратом.
Учитывая задействованные задержки (10 мс) и несколько циклов обработки, даже с 8 потоками вы, вероятно, не так заняты, как вы думаете. Кроме того, вы не указываете, какую виртуальную машину вы используете, но вы можете профилировать разные размеры.
Другой способ сделать это - использовать очередь и несколько «n» рабочих. Для каждого раздела (или набора разделов) поместите сообщение в очередь. Попросите рабочих вытащить из очереди (многопоточную) и запросить / обработать / опубликовать / повторить. Вы можете развернуть столько рабочих, сколько необходимо, и распределить их по большей части центра обработки данных (т.е. с большей пропускной способностью и т. Д.).
Самый быстрый способ получить ваши данные, поддерживаемый Amazon, но еще не Azure, - отправить им USB-диск (даже USB-накопитель), попросить их поместить данные на диск и отправить это обратно к вам.
Другой вариант - использовать служебную шину AppFabric для передачи данных в другую систему при их создании, вместо того, чтобы ждать, чтобы загрузить их все сразу.