Наиболее эффективный дизайн для поиска этих данных в моей базе данных? - PullRequest
0 голосов
/ 28 мая 2009

У меня есть следующие таблицы базы данных и представление, которое представляет эти данные. Таблицы heirachial (если вы так описываете): -

РЕДАКТИРОВАТЬ: я заменил мои 3 таблицы на Фальшивые имена таблиц / данные (для этого поста) потому что я под NDA не публиковать что-нибудь о наших проектах и ​​т.д. да .. я действительно не спасаю людей такие имена:)

FirstNames

FirstNameId INT PK NOT NULL IDENTITY
Name VARCHAR(100)

MiddleNames

MiddleNameId INT PK NOT NULL IDENTITY
Name VARCHAR(100) NOT NULL
FirstNameId INT FK NOT NULL

Фамилия

SurnameId INT PK NOT NULL IDENTITY
Name VARCHAR(100) NOT NULL
FirstNameId INT FK NOT NULL

Итак, имя - это родительская таблица, а две другие таблицы - дочерние.

Вид выглядит как ...

PersonNames

FirstNameId
FirstName
MiddleNameId
MiddleName
SurnameId
Surname

Вот некоторые примеры данных.

FNID FN   MNID    MN     SNID  SN
-----------------------------------
  1  Joe    1   BlahBlah   1  Blogs
  2  Jane   -    -         1  Blogs
  3  Jon    -    -         2  Skeet

Теперь вот проблема. Как я могу эффективно искать имена в представлении ? У меня был полнотекстовый поиск / каталог, но я не могу поставить его на представление (или, по крайней мере, не могу заставить его работать с использованием графического интерфейса пользователя для представления).

РЕДАКТИРОВАТЬ # 2: Вот несколько примеров поисковых запросов: -

exec uspSearchForPeople 'joe blogs'  (1 result)
exec uspSearchForPeople 'joe'        (1 result)
exec uspSearchForPeople 'blogs'      (2 results)
exec uspSearchForPeople 'jon skeet'  (1 result)
exec uspSearchForPeople 'skeet'      (1 result)

Должен ли я создать новую таблицу с полными именами? как это будет выглядеть?

помогите пожалуйста!

Ответы [ 4 ]

0 голосов
/ 19 ноября 2009

Я думаю, что вы хотите Таблица индексов . Неважно, сколько таблиц и столбцов у вас в этих таблицах, поскольку материал вставляется в базу данных, которую он индексирует. напр.

Я бы порекомендовал одну таблицу для ваших имен.

NameTable
----------
Id
FirstName
MiddleName
LastName

Вы можете иметь столько обычных таблиц, сколько захотите ...

IndexTable
----------
Id
Text 

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

IndexItemTable
----------
Id
IndexId // Has a foreign key reference to IndexTable Id
ReferenceId // The record Id of where the text occures
ReferenceTable // The table where the  text occures

Затем, вставляя имя «Джим Барбарович Флеминг», вы также сканируете свой индекс и обнаруживаете, что он пуст, и создаете 3 новые записи для Джима, Барбаровича и Флеминга, которые будут иметь одинаковый referenceId и ReferenceTable будет « NameTable ", затем вы вставляете другую запись, такую ​​как" Джим Брэдли Флеминг ", вы сканируете индексную таблицу и видите, что у вас уже есть значения для" Jim "и" Fleming ", поэтому вы просто создадите IndexItem с referenceId, равным 2, и ReferenceTable, равным" NameTable ". .

Создавая и индексируя, вы можете искать через одно текстовое поле и находить все записи / поля в вашей базе данных, которые имеют эти значения.

Примечание: вы захотите изменить все, когда будете вставлять его в индекс в верхний или нижний регистр, а затем использовать равно (значение, OrdinalIgnoreCase).

Edit: Я не могу просто загрузить изображение. Я должен разместить его где-то, я думаю, но он ничем не отличается от таблиц, которые я привел выше. Единственное отношение IndexTable имеет к IndexItemTable. Я бы сделал все остальное в коде. напр.

Во время вставки или обновления новой записи в таблице имен вам необходимо:

  1. Сканировать IndexTable и посмотреть, существуют ли каждое из полей в NameTable.

  2. Если этого не произойдет, вы добавите в таблицу Index новую запись с текстом, который не был найден. Если они это делают, переходите к шагу 3.

  3. Добавьте запись в IndexItemTable с referenceId (идентификатор записи в NameTable) и ReferenceTable (NameTable), а затем IndexId текста, найденного в IndexTable.

Затем, когда они выполняют поиск по вашему единственному текстовому полю, вы ищете каждое слово в индексной таблице и возвращаете Имена из NameTable, на которые есть ссылки в IndexTable.

0 голосов
/ 28 мая 2009

сумасшедший дизайн, возможно, поддельные имена таблиц делают его более странным, чем он есть.

создание индексов на основе выбранного использования.

если вы ищете по фактическим именам, таким как "Джо", вам нужен индекс FirstNames.Name

если вы ищете по идентификаторам имен, например 123, у вас есть индекс: FirstNames.FirstNameId

если вы хотите искать по FirstNames.name и / или MiddleNames.name и / или Surnames.name, у вас должны быть индексы для комбинаций, которые вы будете использовать, и чем больше вы сделаете, тем сложнее будет выбрать запрос лучший.

отказаться от просмотра и написать специальный запрос для цели:

идти после первого / среднего

select
  FirstNames.name
    ,MiddleNames.name
    ,Surnames.name
  FROM FirstNames
    INNER JOIN MiddleNames ON FirstNames.FirstNameId=MiddleNames.FirstNameId 
    INNER JOIN Surnames ON FirstNames.FirstNameId=Surnames.FirstNameId 
  WHERE FirstNames.Name='John'
    AND MiddleNames.Name='Q'

идти после последнего

select
  FirstNames.name
    ,MiddleNames.name
    ,Surnames.name
  FROM Surnames 
    INNER JOIN FirstNames ON Surnames.FirstNameId =FirstNames.FirstNameId
    INNER JOIN MiddleNames ON FirstNames.FirstNameId=MiddleNames.FirstNameId 
  WHERE Surnames.Name='Public'

просто убедитесь, что у вас есть индексы для покрытия основной таблицы в предложении "where"

используйте SET SHOWPLAN_ALL ON, чтобы убедиться, что вы используете индекс ("сканы" плохие "ищет" хорошие ")

EDIT
если возможно, разбейте имена на части, прежде чем искать их:

exec uspSearchForPeople 'joe',null,'blogs'  (1 result)
exec uspSearchForPeople 'joe',null,null     (1 result)
exec uspSearchForPeople  null,null,'blogs'  (2 results)
exec uspSearchForPeople 'jon',null,'skeet'  (1 result)
exec uspSearchForPeople null,null,'skeet'   (1 result)

внутри хранимой процедуры, есть три запроса:

if @GivenFirstName is not null 
    --search from FirstNames where FirstNames.name=@value & join in other tables
else if @GivenMiddleName is not null 
    --search from MiddleNames where MiddleNames.name=@value & join in other tables
else if @GivenLastName is not null 
    --search from Surnames where Surnames.name=@value & join in other tables
else --error no names given

имеет индекс для всех трех таблиц имен.

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

Просто подумайте о телефонной книге, если вы не используете указатель и ищете имя, вам нужно прочитать всю книгу

0 голосов
/ 28 мая 2009

У меня будет только одна таблица со столбцом типа name (first, middle, last) и FK на себя с кластеризованным индексом в столбце name.

   CREATE TABLE [Name] (
        NameID INT NOT NULL IDENTITY,
        [Name] varchar(100) not null,
        NameType varchar(1) not null,
        FirstNameID int null,
    )

    ALTER TABLE [Name] ADD CONSTRAINT PK_Name  PRIMARY KEY NONCLUSTERED (NameID)
    ALTER TABLE [Name] ADD CONSTRAINT FK_Name_FirstNameID FOREIGN KEY (FirstNameID) REFERENCES [Name](NameID)
    CREATE CLUSTERED INDEX IC_Name ON [Name] ([Name], NameType)

    DECLARE @fid int
    INSERT [Name] ([Name], NameType, FirstNameID) VALUES ('Joe', 'F', NULL)
    SELECT @fid = scope_identity()
    INSERT [Name] ([Name], NameType, FirstNameID) VALUES ('BlahBlah', 'M', @fid)
    INSERT [Name] ([Name], NameType, FirstNameID) VALUES ('Blogs', 'L', @fid)

    INSERT [Name] ([Name], NameType, FirstNameID) VALUES ('Jane', 'F', NULL)
    SELECT @fid = scope_identity()
    INSERT [Name] ([Name], NameType, FirstNameID) VALUES ('Blogs', 'L', @fid)

    INSERT [Name] ([Name], NameType, FirstNameID) VALUES ('Jon', 'F', NULL)
    SELECT @fid = scope_identity()
    INSERT [Name] ([Name], NameType, FirstNameID) VALUES ('Skeet', 'L', @fid)

Затем вы можете построить динамическое, но параметризованное предложение WHERE, основанное на количестве значений для поиска (или жестко запрограммировать их, считая, что их не более 3), используя sp_executsql в хранимом процессе, linq to sql или даже уродливые манипуляции со строками в коде.

0 голосов
/ 28 мая 2009

Это не самое логичное дизайнерское решение. Почему ты так сконструировал это?

Какова ваша структура индексации в настоящее время? Индекс имени на каждой из 3 таблиц должен ускорить запрос?

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

Какова статистика обновлений по сравнению с выбранными, так как добавление этих индексов может привести к снижению производительности.

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