2012-03-28 2 views
2

У нас есть три таблицы, в которых хранятся данные документа, которые я буду называть таблицами A, B и C. В таблице A хранятся основные поля для указанных документов (такие как имя файла и размер и другая общая информация). Чтобы динамически добавлять новые поля, мы используем таблицу B для хранения списка новых полей и их типов данных (определяемых перечислением) и таблицы C для хранения значений для этих полей.Наиболее эффективный способ объединения полей в динамическую структуру таблиц

Table A 
ID - PK int 
FieldX... 
FieldY... 
FieldZ... 

Table B 
Id - PK int 
Name - nvarchar(max) 
Type - int 

Table C 
Id - PK int 
AId - FK to table A int 
BId - FK to table B int 
Value - nvarchar(max) 

Что мы хотим сделать как можно более эффективно, чтобы вытащить значения из таблицы С в качестве дополнительного столбца в запросе из таблицы А. Сейчас здесь, как я делаю это для каждого дополнительного поля Таблица B.

select (select c.value 
     from B b, C c 
     where c.AId = a.Id 
     and c.Bid = b.Id 
     and b.Name = 'Dynamic Field Name') As 'Dynamic Field Name' 
From A a 

У нас есть база данных с таблицей А, заполненная 36000 строк. Для каждого дополнительного динамического поля, которое добавляется к запросу, его добавление около 4 секунд к общему времени для завершения запроса, делая запрос, содержащий 10 динамических полей, занимает не менее 40 секунд. Реально, мы хотим, чтобы любой запрос заканчивался в возрасте до 10. Есть ли способ написать это более эффективно?

+0

Как передать имена динамических полей 'b.Name'? Через список с разделителями-запятыми, жестко закодированный или много аргументов sp? – cctan

ответ

0

Прежде всего, ваш запрос может дать вам ошибки, потому что вы не определили C. (A + B) как уникальные. Если имеется несколько значений в A+B комбинации в C, это приводит к подзапросу к неудаче с

Msg 512, Level 16, State 1, Line 1 
Subquery returned more than 1 value. 

Предполагая, что он уникален, то вы должны быть безопасным только LEFT JOIN их вместе, чтобы использовать операции SET основы.

select a.*, 
     c1.value [Dynamic Field Name 1], 
     c2.value [Dynamic Field Name 2] 
From A a 
JOIN B b1 on b1.Name = 'Dynamic Field Name1' 
LEFT JOIN C c1 on c1.AId = a.Id and c.Bid = b1.Id 
JOIN B b2 on b2.Name = 'Dynamic Field Name2' 
LEFT JOIN C c2 on c2.AId = a.Id and c2.Bid = b2.Id 

Использование подзапроса в силах выбора уровня каждой записи, и каждое динамическое поле, чтобы выполнить как мини-выберите = очень медленно.

+0

Чтобы уточнить, да, значения уникальны, и у вас никогда не будет подзапросов, возвращающих более одного значения. Этот метод был фактически примерно в 100 раз медленнее, чем другой способ, которым я выполнял запросы. Я полагаю, что соединение таблиц намного дороже, чем выбор sub? – user1134837

+0

Зависит от того, какие индексы вы настроили. У вас есть один на 'B.name'? Если нет, создайте его. Ваш запрос будет работать быстрее, если есть очень мало динамических значений, потому что он сначала разрешит ссылку A <-> C и найдет мало что с ней работать. – RichardTheKiwi

0

Возможно, запрос, как это будет работать, а также:

select a.id 
     ,MAX(CASE WHEN b.Name = 'Dynamic Field Name' THEN c.value END) As Dynamic_Field_Name 
     ,MAX(CASE WHEN b.Name = 'Dynamic Field Name 2' THEN c.value END) As Dynamic_Field_Name2 
    from A a, B b, C c 
    where c.AId = a.Id 
    and c.Bid = b.Id 
    and b.Name IN ('Dynamic Field Name', 'Dynamic Field Name 2') 
    group by a.id 

Та же самая идея, вы только хотите сделать один проход по таблице, а не поиска для каждой строки. Агрегат состоит в том, чтобы сжать разреженную матрицу в одну строку (т. Е. Будет только одно значение динамического поля в строке, причем каждая строка имеет другой столбец со значением). Не знаю, как это будет выполняться.

+0

Вам нужны левые соединения, иначе вы потеряете записи, где динамические поля пусты. – RichardTheKiwi

+0

@Richardakacyberkiwi Согласен. Это предполагает, что если динамические поля перечислены в предложении «in», они фактически существуют со значениями. – Glenn

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