Посмотрите на эту psuedo схему (пожалуйста, обратите внимание, что это является упрощением, поэтому постарайтесь не слишком комментировать "целесообразность" самой схемы). Предположим, что индексы установлены на FK.
TABLE Lookup (
Lookup_ID int not null PK
Name nvarchar(255) not null
)
TABLE Document (
Document_ID int not null PK
Previous_ID null FK REFERENCES Document(Document_ID)
)
TABLE Document_Lookup (
Document_ID int not null FK REFERENCES Document(Document_ID)
Lookup_ID int not null FK REFERENCES Lookup(Lookup_ID)
)
Объемы: Документ, 4 миллиона строк, из которых 90% имеют нулевое значение поля Previous_ID; Lookup, 6000 строк, Среднее количество просмотров, прикрепленных к каждому документу 20, что дает Document_Lookup 80 миллионов строк.
Теперь в .NET Service есть структура для представления строки Lookup следующим образом:-
struct Lookup
{
public int ID;
public string Name;
public List<int> DocumentIDs;
}
и что строки Lookup хранятся в Dictionary
, где ключом является ID Lookup. Важным моментом здесь является то, что этот словарь должен содержать записи, где на Lookup ссылается хотя бы один документ, т.е. список DocumentIDs
должен иметь Count > 0.
Моя задача - эффективно заполнить этот словарь. Поэтому простой подход был бы следующим:-
SELECT dl.Lookup_ID, l.Name, dl.Document_ID
FROM Document_Lookup dl
INNER JOIN Lookup l ON l.Lookup_ID = dl.Lookup_ID
INNER JOIN Document d ON d.Document_ID = dl.Lookup_ID
WHERE d.Previous_ID IS NULL
ORDER BY dl.Lookup_ID, dl.Document_ID
Это можно использовать для достаточно эффективного заполнения словаря.
Вопрос: Выполняет ли базовая доставка набора рядов (TDS?) некоторую оптимизацию? Мне кажется, что запросы, которые де-нормализуют данные, очень распространены, поэтому вероятность того, что значения полей не меняются от строки к строке, высока, поэтому было бы логично оптимизировать поток, не отправляя значения полей, которые не изменились. Кто-нибудь знает, существует ли такая оптомизация? (Оптомизации, похоже, не существует).
Какой более сложный запрос я мог бы использовать для устранения дублирования (я имею в виду повторение значения имени)? Я слышал о такой вещи, как "вложенный набор рядов", можно ли сгенерировать такую вещь? Будет ли он более производительным? Как мне получить к нему доступ в .NET?
Я бы выполнил два запроса: один для заполнения словаря Lookup, второй для заполнения списков ditionary. Затем я бы добавил код для удаления неиспользуемых записей Lookup. Однако представьте, что я ошибся в своих прогнозах, и Lookup в итоге составил 1 миллион строк, и только четверть из них действительно ссылается на какой-либо документ?