SQL Server 2012 Многие родители присоединяются к таблицам?

У меня есть одна таблица ("#detail" в примере ниже), которая будет иметь дочернее отношение к одной из трех таблиц (всегда одна таблица и никакие другие). Например, строки #detail 'aaaa' и 'bbbb' должны иметь значение столбца, связанное с #metainfo1, row1 и row 'cccc' должны быть связаны с #metainfo2.row1, а 'dddd' должно быть связано с #metainfo3, ряд1.

Я бы предпочел не создавать новый столбец в #detail для каждой таблицы #metainfo, потому что мне придется добавлять новые столбцы #detail по мере добавления новых таблиц #metainfo во время существования базы данных, и каждая строка в #detail будет иметь не менее 2 нулевых значений (и больше нулевых столбцов по мере роста #metainfo).

Я думал о создании таблицы соединений/соединений между таблицами #detail и #metainfo, но это просто перемещает лишние нулевые столбцы и работу по расширению в другую таблицу (и добавляет дополнительный ввод-вывод).

Может ли кто-нибудь порекомендовать способ заставить эти отношения с несколькими родителями работать?

Спасибо.

create table #detail (detailid int identity(1,1) primary key , detailinfo varchar(4) )
create table #metainfo1 (meta1id int primary key )
create table #metainfo2 (meta2id int primary key)
create table #metainfo3 (meta3id int primary key)
insert into #detail 
   select 'aaaa' union select 'bbbb' union select 'cccc' union select 'dddd'
insert into #metainfo1 
   select 1 
insert into #metainfo2
   select 1 
insert into #metainfo3
   select 1 

person Snowy    schedule 14.09.2013    source источник


Ответы (1)


Я бы рекомендовал нормализовать ваши данные, чтобы метаинформация была объединена в одну таблицу. Давайте составим схему:

MetaInfotypes (parent) --1-to-many--> MetaInfo (child)
MetaInfo (parent) --1-to-many--> Detail (child)

Это означает: Одна или несколько деталей будут связаны с метаинформацией. Одна или несколько метаданных будут связаны с типом.

Давайте посмотрим на структуру таблиц:

-- Example: MetaInfo1, MetaInfo2, MetaInfo3
create table MetaInfoTypes (
  id int identity(1, 1) primary key, 
  name varchar(20), 
  constraint uk_MetaInfoTypes_name unique(name)
);

create table MetaInfo (
  id int identity(1,1) primary key,  
  MetaInfotypeid int,
  somevalue varchar(100),
  foreign key (MetaInfotypeid) references MetaInfoTypes(id)
);

create table detail (
  detailid int identity(1,1) primary key, 
  detailinfo varchar(4),
  MetaInfoid int,
  foreign key (MetaInfoid) references MetaInfo(id)
);

Посмотрите на этот SQLFiddle с фиктивными данными.

Таким образом, вам не придется добавлять таблицы MetaInfo. Вы просто поместите данные в таблицу MetaInfo и просто определите тип MetaInfo. Чтобы легко добавлять типы, у нас есть таблица MetaInfoTypes. Затем просто свяжите деталь с выбранной метаинформацией, и все готово.

Когда необходимо добавить новую метаинформацию, добавьте ее в MetaInfoType. Затем добавьте данные в MetaInfo для этого типа. Затем добавьте данные к деталям и укажите идентификатор MetaInfo.

person zedfoxus    schedule 15.09.2013
comment
Потрясающий! Я загрузил некоторые тестовые данные (типы 1000 строк, метаинформация 9999 строк, детализация 4,6 млн строк), и это быстро! План выполнения в моей системе Sql2012 показывает сканирование кластеризованного индекса по деталям, которые я не могу устранить. Ты знаешь почему? Спасибо! - person Snowy; 16.09.2013
comment
Можете ли вы опубликовать заявление, которое вы проанализировали с планом выполнения? Я, конечно, могу посмотреть, как это можно оптимизировать. - person zedfoxus; 16.09.2013
comment
Это тот же план, который показан с SqlFiddle, сканирование кластеризованного индекса занимает около 30% плана (другие 2 операции — поиск CI), я играл с включением столбцов в подробную таблицу, но все же получил сканирование. - person Snowy; 16.09.2013
comment
Привет, @Snowy, у тебя хороший глаз. Сканирование CI должно произойти хотя бы на одной таблице. Например, дайте мне все из деталей, и для каждой строки деталей получите метаинформацию, а для каждой строки метаинформации получите метаинформацию. Таким образом, детали сканируются, а остальные проходят поиск CI. Если вы сделаете where detailid = 1, детали будут искать CI. Если вы часто выполняете поиск в detailinfo, добавьте некластеризованный индекс в detailinfo, чтобы он выполнял RID в дополнение к поиску NCI. - person zedfoxus; 16.09.2013