2016-11-03 6 views
0

У меня возник вопрос о выборе ключа раздела DocumentDB. У меня есть данные с UserId, DeviceId и WhateverId. Параметр UserId всегда будет в запросах, поэтому я выбрал UserId в качестве ключа раздела. Но у меня много данных для одного пользователя (миллионы объектов), и когда я сделал quety, как "SELECT * FROM c WHERE c.DeviceId = @DeviceId" с указанным ключом раздела, требуется много времени (около 6 минут для около 220 000 возвращенных объектов). Возможно, было бы более эффективным выбрать, например, DeviceId в качестве ключа раздела и делать запросы против нескольких разделов параллельно (с указанием EnableCrossPartitionQuery = true и MaxDegreeOfParallelism = количество разделов)? Или, может быть, это хорошая идея использовать отдельную коллекцию для каждого пользователя?Ключ раздела для DocumentDB

+0

Не то, чтобы это отвечало на ваш вопрос, но ... Я думаю, что в любое время, когда вы пытаетесь извлечь четверть миллиона объектов, вам может потребоваться переосмыслить ваш шаблон доступа к данным. Кроме того, «SELECT *' »является еще одним кодовым запахом. Я не вижу, как ваш выбор ключа раздела будет иметь значение, если вы пытаетесь переместить столько данных в ваш уровень приложения. –

+0

Спасибо. 'SELECT *' был просто для быстрого примера, извините. Я буду использовать 'SELECT c.Value'. И этот вопрос касается выбора ключа раздела, поскольку информация о сайте документации на лазурном языке немного абстрактна, как и для меня. Все эти измерения предназначены только для сравнения производительности в зависимости от запроса. – Paval

ответ

1

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

Вы можете поэкспериментировать с ключом раздела, чтобы улучшить parrallism, но, в лучшем случае, это обеспечит вам улучшение в 2-5 раз по сравнению с моим опытом. Этого достаточно?

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

+0

Я изменил ключ раздела на DeviceId и попытался сделать запрос как 'SELECT c.Value FROM c WHERE c.UserId = @userId и c.WhateverId = @ WhateverId'. Для 19845 возвращенных объектов потребовалось 4.6. Все в порядке. Но когда я попытался запросить ключ раздела, например 'SELECT c.Value FROM c WHERE c.UserId = @userId и c.DeviceId = @ DeviceId', потребовалось около 27 секунд почти для того же количества возвращенных объектов. И это плохо, потому что запросы с DeviceId чаще используются. Я понимаю, что это произошло потому, что когда мы указываем ключ раздела, параллелизм отсутствует. Должен ли я рассмотреть другой pk – Paval

+1

Ключ в том, что вам придется продолжать экспериментировать. Не забудьте включить настройку индекса в свои эксперименты. Клавиши индекса по умолчанию отключены от первых 3 байтов данных. Если это не изменится достаточно, вы можете получить горячую точку индекса. –

+0

Вы имеете в виду, что это произойдет, если у меня будет много ключей, начинающихся с одних и тех же символов, правильно. – Paval

0

Я знаю, что это немного старое, но на благо других, приезжающие в эту тему ...

Из вашего описания я полагаю, что эти устройства являются в основном уникальными для пользователя. Часто рекомендуется разделять что-то вроде userid, что хорошо, если у вас есть, скажем, приложение для колл-центра, со многими запросами для данного идентификатора пользователя и хотите найти не более нескольких сотен записей. В таких случаях данные могут быть быстро извлечены из одного раздела без накладных расходов при сопоставлении данных по разделам. Однако, если у вас есть миллионы записей для пользователя, то разделение на ИД пользователя, пожалуй, самый худший вариант, так как извлечение больших объемов данных из одного раздела скоро превысит накладные расходы на сортировку. В таких случаях вы хотите распределить данные пользователя как можно более равномерно по всем разделам. Если у каждого пользователя нет более 25 устройств с аналогичным использованием, то идентификатор устройства, вероятно, тоже не является хорошим выбором.

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

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