Давайте поговорим о производительности
Первый пункт: старайтесь избегать скалярных функций и старайтесь избегать TVF-операторов с несколькими утверждениями , если это возможно.Единственный быстрый подход - это inline-TVF ( однострочный оператор ).
Второй момент: избегайте петель, если когда-либовозможно!
Третий пункт ( самый первый на самом деле ): попытайтесь сохранить ваши данные в формате, оптимизированном для быстрых запросов.Хранение более одного значения в одной ячейке нарушает 1NF и приводит к огромной скорости убийцы.
Вы можете попробовать это:
Имитация ваших таблиц
CREATE TABLE #t100(ID INT IDENTITY,SomeName VARCHAR(200));
CREATE TABLE #t1M (ID INT IDENTITY,SomeName VARCHAR(200));
INSERT INTO #t100 VALUES('james smith'),('mak john'),('Luke W');
GO
INSERT INTO #t1M values('John A Mak'),('K Smith Will'),('James Henry'),('James John'),('Some other');
GO
- Создать таблицы для отдельного хранения фрагментов имени (именно этот формат вы должны использовать вместо этого на самом деле)
CREATE TABLE #t100Splitted(ID INT IDENTITY PRIMARY KEY,ID_t100 INT,Fragment NVARCHAR(200));
--Use an inline XML-splitter
INSERT INTO #t100Splitted(ID_t100,Fragment)
SELECT ID
,B.frg.value('text()[1]','nvarchar(200)')
FROM #t100
CROSS APPLY(SELECT CAST('<x>' + REPLACE((SELECT SomeName AS [*] FOR XML PATH('')),' ','</x><x>') + '</x>' AS XML)) A(CastedToXml)
CROSS APPLY A.CastedToXml.nodes('/x[text()]') B(frg);
--add indexes
CREATE INDEX IX_t100_ID_t100 ON #t100Splitted(ID_t100);
CREATE INDEX IX_t100_Fragment ON #t100Splitted(Fragment);
--The same for the second table
CREATE TABLE #t1MSplitted(ID INT IDENTITY PRIMARY KEY,ID_t1M INT,Fragment NVARCHAR(200));
INSERT INTO #t1MSplitted(ID_t1M,Fragment)
SELECT ID
,B.frg.value('text()[1]','nvarchar(200)')
FROM #t1M
CROSS APPLY(SELECT CAST('<x>' + REPLACE((SELECT SomeName AS [*] FOR XML PATH('')),' ','</x><x>') + '</x>' AS XML)) A(CastedToXml)
CROSS APPLY A.CastedToXml.nodes('/x[text()]') B(frg);
CREATE INDEX IX_tM_ID_t100 ON #t1MSplitted(ID_t1M);
CREATE INDEX IX_tM_Fragment ON #t1MSplitted(Fragment);
GO
- Check the intermediate results
SELECT * FROM #t100Splitted;
SELECT * FROM #t1MSplitted;
GO
- Этот запрос вернет все строки с общими фрагментами
--Вы можетеповторно объедините ваши исходные таблицы, чтобы получить значения обратно
- Вы можете сгруппировать по t2.ID_t100, чтобы получить идентификаторы меньшей таблицы (намного быстрее)
SELECT t1.ID_t1M
FROM #t1MSplitted t1
INNER JOIN #t100Splitted t2 ON t1.Fragment=t2.Fragment
GROUP BY t1.ID_t1M
GO
- Очиститьup
DROP TABLE #t100;
GO
DROP TABLE #t1M;
GO
DROP TABLE #t100Splitted;
GO
DROP TABLE #t1MSplitted;
GO
В моей системе 1 строка Mio была обработана примерно за 2 минуты.
UPDATE - Тесты производительности с 100 строками против 10M рядов
(с очень большим количеством обращений)
Просто разделение , чтобы преобразовать ваши данные в лучшую форму: ~ 17 минут
Окончательный выбор (только поиск): <1 минута </em>
Окончательный выбор но ищем идентификаторы маленькой таблицы: несколько секунд
(после преобразования данных это будет нормальная скорость )
Подход PSK (с разделением строк): ~ 30 минут