Полнотекстовый поиск поля URL sql server

цель: вернуть все URL-адреса, начинающиеся с "https://mywebsite.domain.com/as/product/4/"

дано:

  • применяется полнотекстовый поиск в поле URL.
  • SQL Server edition: 2014.
  • 20+ миллионов строк

URL-адресом

https://mywebsite.domain.com/as/product/1/production
https://mywebsite.domain.com/as/product/2/items
https://mywebsite.domain.com/as/product/1/affordability
https://mywebsite.domain.com/as/product/3/summary
https://mywebsite.domain.com/as/product/4/schedule
https://mywebsite.domain.com/as/product/4/resources/summary

запрос 1:

WHERE CONTAINS (URL, 'https://mywebsite.domain.com/as/product/4')

результат:

All records returned

запрос 2 (добавил "*" после прочтения в MSDN статья)

WHERE CONTAINS (URL, '"https://mywebsite.domain.com/as/product/4*"')

результат:

No records returned

любая помощь была бы весьма признательна.

5 ответов


можно использовать CONTAINS С LIKE подзапрос для сопоставления только начала:

SELECT * 
FROM (
SELECT * 
FROM myTable WHERE CONTAINS (URL, '"https://mywebsite.domain.com/as/product/4/"')
) AS S1 
WHERE S1.URL LIKE 'https://mywebsite.domain.com/as/product/4/%' 

таким образом,медленно LIKE запрос оператора будет выполняться для меньшего набора записей

EDIT1: (если WHERE CONTAINS (URL, '"https://mywebsite.domain.com/as/product/4/"') Не фильтрует значения)

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

читать эти темы:

EDIT2:

я нашел одно предлагаемое решение, которое

/ рассматривается как английский wordbreaker вы можете изменить его от Реестр

  • перейдите к значениям реестра HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SQL Server\<InstanceRoot>\MSSearch\Language\eng и HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SQL Server\<InstanceRoot>\MSSearch\Language\enu
  • очистить значение для WBreakerClass.

Sql server рассмотреть https://mywebsite.domain.com/as/product/4 как одно слово.

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

подробнее о Word Breaker в этом раздел MSDN


использовать Like оператор:

WHERE URL LIKE 'https://mywebsite.domain.com/as/product/4%'

на % является подстановочным. Это должно возвращать все записи, которые начинаются с шаблона, совпадающего с первым подстановочным знаком %.


при условии, что вы всегда ищете начало строки, это гарантирует, что оптимизатор может использовать индекс. Я предполагаю, что URL-адрес VARCHAR

Declare @p varchar(500) ='https://mywebsite.domain.com/as/product/4'

Declare @maxChar char(1);
select @maxChar = max(ch)
from (
    select top(256) ch = char(row_number() over(order by (select null)) - 1)
    from sys.all_objects) t;
select @maxChar;

-- ..
WHERE URL > @p AND URL < @p + @maxChar

при сравнении строк Sql server добавляет конечные пробелы к более коротким. См.https://support.microsoft.com/en-us/kb/316626 . Согласно http://www.ietf.org/rfc/rfc1738.txt , http://www.ietf.org/rfc/rfc1738.txt все разрешенные символы URL больше, чем пробел. Итак, параметр поиска,'https://mywebsite.domain.com/as/product/4' для например, будет меньше любого URL, который начинается с этого параметра и превышает длину параметра.


для подобных проблем я привык к двум решениям, в зависимости от ваших потребностей, в основном от performaces или ресурсов или параллелизма.. и т. д. и т. п..

The LIKE оператор может быть вашим лучшим другом также с очень большими таблицами.

индексации
Прежде всего, вам нужно проиндексировать столбец url, работая с 20 + миллионами записей это непростая задача, индексация это может стоить 1.5 - 2.0 Гб дискового пространства, но вы получите свой запрос в кратчайшие сроки (миллисекунды)

с индексом на столбце для поиска,LIKE FixedPattern+% выполняется с индексом seek,вы не можете улучшить его дальше.

первый вариант:

CREATE NONCLUSTERED INDEX [IX_URL] ON [url_table] ([url]);

DECLARE @Domain VARCHAR(100) = 'https://mywebsite.domain.com/'
DECLARE @Path VARCHAR(100) = 'as/product/'
DECLARE @Product VARCHAR(20) = '4'
DECLARE @LikeAll VARCHAR(100) = @Domain + @Path + @Product + '/%'

SELECT url
FROM url_table
WHERE url LIKE @LikeAll

второй вариант
Второй вариант немного сложный, но очень эффективный.
Вы сказали, что протокол и домен url исправлены, и вам нужно что-то искать после.
Ниже приведен метод, вы можете настроить это соответствует вашим потребностям.
Идея состоит в том, чтобы добавить виртуальный (вычисляемый) столбец в таблицу url, а затем добавить на него индекс.
Это значительно уменьшит размеры индекса и улучшит производительность запросов за счет очень небольших затрат на вычисления в insert/update

ALTER TABLE url_table ADD path AS (SUBSTRING(url, 30, 4000));
CREATE NONCLUSTERED INDEX [IX_PATH] ON [url_table] ([path]);

DECLARE @Domain VARCHAR(100) = 'https://mywebsite.domain.com/'
DECLARE @Path VARCHAR(100) = 'as/product/'
DECLARE @Product VARCHAR(20) = '4'
DECLARE @LikeMid VARCHAR(100) = @Path + @Product + '/%' 

select @Domain + _path -- pay attention!!
FROM url_table
WHERE url LIKE @SrcAll

обратите внимание, мы выбираем @Domain + _path вместо url, чтобы избежать доступа к таблице и работать только с индексными данными.

Если вам нужны другие столбцы в url_table, ваш лучший вариант is

declare @l table (id int primary key)
insert  into @l
select id 
from url_table 
where _path like @LikeMid

select url
from url_table
where id in (select id from @l)

очень быстро

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

ALTER TABLE url_table ADD _product AS (cast(substring(url,nullif(CHARINDEX('/product/',url,29)+9,9), CHARINDEX('/',url,nullif(CHARINDEX('/product/',url,29)+9,9))-nullif(CHARINDEX('/product/',url,29)+9,9)) as bigint));
CREATE NONCLUSTERED INDEX [IX_PRODUCT] ON [url] ([_product]);

select id, url
from url_table 
where _product = 4

это произведет вычисляемый столбец с номером продукта типа integer, индекс будет только 500Mb и запросы на целых числах будут супер быстрыми.
Также надбавки к выберите все столбцы из url_table очень мало, поэтому вы можете SELECT * почти без проблем выступлений.

С. П. Вы можете удалить свой полнотекстовый индекс и сэкономить место и ресурсы..


SELECT * FROM myTable WHERE URL LIKE 'https://mywebsite.domain.com/as/product/4%'