Как я могу ускорить мой код разбиения на страницы в ASP.NET MVC с Azure? - PullRequest
1 голос
/ 21 сентября 2009

Я использую ASP.NET MVC и хранилище таблиц Azure в локальной структуре разработки. Мой код нумерации страниц очень медленный при работе с большим набором результатов:

var PageSize = 25;
var qResult2 = from c in svc.CreateQuery<SampleEntity>(sampleTableName)
                           where c.PartitionKey == "samplestring"
                           select c;
TableStorageDataServiceQuery<SampleEntity> tableStorageQuery = 
                 new TableStorageDataServiceQuery<SampleEntity>
                 (qResult2 as DataServiceQuery<SampleEntity>);
var result = tableStorageQuery.ExecuteAllWithRetries()
                                .Skip((page - 1) * PageSize)
                                .Take(PageSize);
var numberOfEntities = tableStorageQuery.ExecuteAllWithRetries().Count
ViewData["TotalPages"] = (int)Math.Ceiling((double) numberOfEntities / PageSize);
ViewData["CurrentPage"] = page;
return View(result);

ViewData используется View для вычисления ссылок на страницы с использованием кода из книги Сандерсона MVC. Для таблицы Azure с 1000+ сущностями это очень медленно. Для начала, «Подсчет» занимает довольно много времени, чтобы рассчитать общее количество сущностей. Если я правильно читаю свою книгу LINQ, это потому, что запрос не реализует ICollection. Книга "Pro LINQ" Джозефа Ратца.

Даже если я установлю «numberOfEntities» на известную сумму (например, 1500), подкачка будет медленной для страниц выше 10. Я предполагаю, что .Skip и / или .Take медленные. Кроме того, я дважды вызываю ExecuteAllWithRetries (), и это не поможет, если на самом деле Azure запрашивается дважды.

Какую стратегию следует использовать для разбивки на большие наборы данных в ASP.NET MVC и Azure?

РЕДАКТИРОВАТЬ: мне не нужно знать точное общее количество страниц.

1 Ответ

4 голосов
/ 21 сентября 2009

Skip и Take здесь не являются проблемой - они будут выполняться против IEnumerable, который уже будет в памяти и, следовательно, очень быстрым.

ExecuteAllWithRetries, вероятно, является виновником - вы в основном извлекаете все объекты в разделе из удаленного хранилища в этом вызове, что приведет к очень большой полезной нагрузке.

Нумерация страниц, как вы показываете, довольно сложна в Table Storage. Вот несколько вопросов:

  • Единственный гарантированный заказ - это заказ PartitionKey / RowKey, поэтому вам необходимо разработать свой RowKeys с учетом этого.

  • Вы можете выполнить Take в запросе (т. Е. Ваш qResult2), так что это уменьшит количество сущностей, проходящих по проводу.

  • Для выполнения функций, подобных Skip, вам нужно использовать оператор сравнения. Поэтому вам нужно знать, где вы находитесь в наборе результатов, и запросить все RowKeys выше этого значения (т. Е. Добавить что-то вроде where c.RowKey > [lastRowKey] в ваш запрос)

  • Невозможно получить счет, не отслеживая его самостоятельно (или не извлекая всю таблицу, как вы уже делаете). В зависимости от вашего дизайна, вы можете хранить счетчик вместе с каждым объектом (т. Е. Использовать возрастающее значение) - но просто убедитесь, что вы отслеживаете параллельные конфликты редактирования и т. Д. Если вы отслеживаете счетчик с каждым объектом, то Вы также можете выполнить свой Skip, используя это тоже. Другой вариант - сохранить счет в одном значении в другом объекте (вы можете использовать ту же таблицу для обеспечения транзакционного поведения). Вы также можете объединить эти подходы (сохранить счет в одном объекте, чтобы получить оптимистичный параллелизм, а также сохранить его в каждом объекте, чтобы вы знали, где он находится).

  • Альтернативой будет, если это возможно, полностью избавиться от счета. Вы заметите, что несколько крупных масштабируемых сайтов делают это - они не предоставляют точный список того, сколько страниц существует, но они могут позволить вам перейти на пару страниц вперед / назад. Это в основном устраняет необходимость в подсчете - вам просто нужно отслеживать RowKeys для следующих / предыдущих страниц.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...