А я сегодня LIKE проиндексировал :)

Аватара пользователя
Dmitry67
Уже с Приветом
Сообщения: 28294
Зарегистрирован: Вт авг 29, 2000 4:01 am
Откуда: SPB --> Gloucester, MA, US --> SPB --> Paris
Контактная информация:

А я сегодня LIKE проиндексировал :)

Сообщение Dmitry67 »

subj

Есть огромная таблица

IDdocument (unique)
StrData varchar ...

Идут поиски по StrData like '%something%'
Full Text Indexing не работает потому что работает по словам
А надо именно поведение like, то есть

like '%ion typ%' найдет 'production type'
а full text index не найдет

Так вот, придумал я индекс
Работает, собака. Быстро, почти мгновенно
А Вы бы как поступили ?
Зарегистрированный нацпредатель, удостоверение N 19719876044787 от 22.09.2014
Аватара пользователя
YellowMan
Уже с Приветом
Сообщения: 1099
Зарегистрирован: Чт сен 30, 1999 4:01 am
Откуда: Bryansk,RUSSIA >> Dublin, Ireland
Контактная информация:

Сообщение YellowMan »

Создать вьюху/другую таблицу, связать исходную и новою по ID, в новой перебрать все варианты 'production type', проиндексировать новую таблицу ?
Вроде как

ID Variant
production type production type
production type roduction type
production type oduction type

и т.д....
Таблица будет огромная но индекс будет работать, потом можно будет писать вместо like '%blah%' просто like 'blah%' если места жалко :)
Удачи@С.Смирнов
Аватара пользователя
Dmitry67
Уже с Приветом
Сообщения: 28294
Зарегистрирован: Вт авг 29, 2000 4:01 am
Откуда: SPB --> Gloucester, MA, US --> SPB --> Paris
Контактная информация:

Сообщение Dmitry67 »

И индеск огромный
У меня решение более сложное но более экономное
Впрочем и Ваш вариант сравню...
Зарегистрированный нацпредатель, удостоверение N 19719876044787 от 22.09.2014
Аватара пользователя
tengiz
Уже с Приветом
Сообщения: 4468
Зарегистрирован: Чт сен 21, 2000 4:01 am
Откуда: Sammamish, WA

Сообщение tengiz »

Существует разные варианты, какой именно является наиболее подходящим, зависит от дополнительных обстоятельств. Например - насколько важна скорость создания такого "индекса"? Другими словами, является ли Ваша таблица read-mostly? Да, и о каком сервере БД идёт речь - это MSSQL?
Cheers
Аватара пользователя
CTAC_P
Уже с Приветом
Сообщения: 6789
Зарегистрирован: Пт июн 01, 2001 4:01 am

Сообщение CTAC_P »

Я бы зафигачил по пронципу LZW компрессии. Работать будет чуть подольше, зато индекс будет компактный.
lozzy
Уже с Приветом
Сообщения: 2435
Зарегистрирован: Вт июн 12, 2001 4:01 am

Re: А я сегодня LIKE проиндексировал :)

Сообщение lozzy »

Dmitry67 писал(а):Так вот, придумал я индекс
Работает, собака. Быстро, почти мгновенно
А Вы бы как поступили ?


Какой-нибудь soundex, metaphone или levenshtein ? ;)
Steel helmet protects your teeth from the morning to the evening.
Аватара пользователя
Dmitry67
Уже с Приветом
Сообщения: 28294
Зарегистрирован: Вт авг 29, 2000 4:01 am
Откуда: SPB --> Gloucester, MA, US --> SPB --> Paris
Контактная информация:

Сообщение Dmitry67 »

Еще раз полумал об усечении строк - 'alpha', 'lpha', 'pha', 'ha' - нет, так никакого места не хватит
И индекс огромный будет (а поле кстати varchar(4000))
У меня другая идея

Напишу сегодня или завтра после ряда экспериментов
Зато дам развернутый ответ
Но если у кого идеи есть пишите, тема то интересная...
Зарегистрированный нацпредатель, удостоверение N 19719876044787 от 22.09.2014
Аватара пользователя
YellowMan
Уже с Приветом
Сообщения: 1099
Зарегистрирован: Чт сен 30, 1999 4:01 am
Откуда: Bryansk,RUSSIA >> Dublin, Ireland
Контактная информация:

Сообщение YellowMan »

Было бы здорово узнать Вашу идею - пока я не вижу никакого варианта кроме как КАЖДЫЙ СИМВОЛ ( или его ASCII код) из varchar(4000) ДОЛЖЕН СТОЯТЬ ПЕРВЫМ в индексе.
Можно конечно так и оставлять по одной букве на строку индекса, но селективность будет ужасная, вернее count(*)*4000/число букв в алфавите.

А насчет огромного индекса - место это сейчас только финансовая проблема, зато за счет почти идеальной селективности дерево будет обходиться очень быстро. Пробдемы будут при массовой вставке, но и это можно решить, в том числе и выносом поиска на отдельный сервер.
Удачи@С.Смирнов
Yuri_p33
Уже с Приветом
Сообщения: 394
Зарегистрирован: Пн фев 12, 2001 4:01 am
Откуда: USA

Re: А я сегодня LIKE проиндексировал :)

Сообщение Yuri_p33 »

Dmitry67 писал(а):Full Text Indexing не работает потому что работает по словам
А не пробовали такой подход - создать еще одно текстовое поле и занести туда содержимое первого, но превратив буквы в слова, т.е.
StrData - 'рыжая лисица'
StrDataNew - 'р ы ж а я л и с и ц а'
По второму полю сделать Full Text Index. Вместо LIKE '%something%' использовать CONTAINS ('s o m e t h i n g *').
?
Аватара пользователя
Dmitry67
Уже с Приветом
Сообщения: 28294
Зарегистрирован: Вт авг 29, 2000 4:01 am
Откуда: SPB --> Gloucester, MA, US --> SPB --> Paris
Контактная информация:

Re: А я сегодня LIKE проиндексировал :)

Сообщение Dmitry67 »

Yuri_p33 писал(а):
Dmitry67 писал(а):Full Text Indexing не работает потому что работает по словам
А не пробовали такой подход - создать еще одно текстовое поле и занести туда содержимое первого, но превратив буквы в слова, т.е.
StrData - 'рыжая лисица'
StrDataNew - 'р ы ж а я л и с и ц а'
По второму полю сделать Full Text Index. Вместо LIKE '%something%' использовать CONTAINS ('s o m e t h i n g *').
?


Не получится CONTAINS ('s o m e t h i n g *')
Надо писать CONTAINS('s') and CONTAINS('o') итд
И еще порядок важен
А селективность по CONTAINS('s') никакая..

Пока результат мой
В таблице из 350000 ищу за max 200ms если записей <100
Если плохая селективность то дольше значительно
Объем данных индексных таблиц правда в 20 раз больше талицы строк
Но только в 2 раза больше объема самих документов... не так плохо...
Зарегистрированный нацпредатель, удостоверение N 19719876044787 от 22.09.2014
Yuri_p33
Уже с Приветом
Сообщения: 394
Зарегистрирован: Пн фев 12, 2001 4:01 am
Откуда: USA

Re: А я сегодня LIKE проиндексировал :)

Сообщение Yuri_p33 »

Dmitry67 писал(а):Не получится CONTAINS ('s o m e t h i n g *')
Почему не получится? Я, правда, этот фулл текст индекс никогда не юзал, но судя по документации вроде должно работать...
Давайте немного изменим мой пример -
StrData - 'рыжая лисица'
StrDataNew - 'рблин ыблин жблин аблин яблин блин лблин иблин сблин иблин цблин аблин'
и вместо LIKE '%something%' пользуем CONTAINS("sблин oблин mблин eблин tблин hблин iблин nблин gблин", т.е. поиск по точной фразе. Вроде, должен работать. Другой вопрос - как :)

А вот другое решение - для каждой стоки StrData выделяем все подстроки, в спец. таблице храним номер символа начала подстроки, номер символа конца и какой-нибудь ее хеш-код (например, CHECKSUM(подстрока)). Индексируем по хеш-коду. Для каждого LIKE 'something' выбираем строки из спец. таблицы где хеш-код = хеш_код('something') и сравниваем соответствующую подстроку с 'something' на точное равенство.

Да, еще хорошо бы искать не только на совпадение хеш-кода, но и длины подстроки. Да и выделять не все подстроки, а только, допустим, начиная от 3-х символов и до 50-ти, например. Никто ведь не будет вводить 4000 символов как условие поиска.
Последний раз редактировалось Yuri_p33 Ср окт 08, 2003 12:47 pm, всего редактировалось 1 раз.
Аватара пользователя
Dmitry67
Уже с Приветом
Сообщения: 28294
Зарегистрирован: Вт авг 29, 2000 4:01 am
Откуда: SPB --> Gloucester, MA, US --> SPB --> Paris
Контактная информация:

Сообщение Dmitry67 »

select * from FTS_strings where CONTAINS(str, 'a')

Serveur : Msg 7619, Niveau 16, État 1, Ligne 1
Execution of a full-text operation failed. A clause of the query contained only ignored words.

select * from FTS_strings where CONTAINS(str, 'a near b')
Serveur : Msg 7619, Niveau 16, État 1, Ligne 1
Execution of a full-text operation failed. A clause of the query contained only ignored words.
Зарегистрированный нацпредатель, удостоверение N 19719876044787 от 22.09.2014
Yuri_p33
Уже с Приветом
Сообщения: 394
Зарегистрирован: Пн фев 12, 2001 4:01 am
Откуда: USA

Сообщение Yuri_p33 »

Dmitry67 писал(а):Execution of a full-text operation failed. A clause of the query contained only ignored words.
Да, действительно...
Noise words (such as a, and, or the) in full-text indexed columns are not stored in the full-text index. If a noise word is used in a single word search, SQL Server returns an error message indicating that only noise words are present in the query. SQL Server includes a standard list of noise words in the directory \Mssql\Ftdata\Sqlserver\Config.
Но с ключевой добавкой "блин"(или как там по французки? :) ) все должно работать.
hb
Сообщения: 14
Зарегистрирован: Пн июн 04, 2001 4:01 am
Откуда: Pandora's box

Сообщение hb »

Покажите, пожалуйста, select avg(len(StrData)) from ...

У каждого решения есть границы применимости. То, что в StrData может быть до 4000 символов, мало о чем говорит. Важнее, сколько символов, в среднем, есть на самом деле.
8K
Уже с Приветом
Сообщения: 5552
Зарегистрирован: Вт мар 20, 2001 4:01 am
Откуда: SFBA

Re: А я сегодня LIKE проиндексировал :)

Сообщение 8K »

Dmitry67 писал(а):придумал я индекс
Работает, собака. Быстро, почти мгновенно
А Вы бы как поступили ?

Ну, в качестве идеи, разве что.

Разбивать исходную строчку на группы по четыре символа. Превращать их в целые числа и складывать в другую таблицу, там индексировать. При поиске строку-шаблон подвергнуть аналогичному препарированию (еще надо сдвигать по одному символу четыре раза, т.к. match не обязательно начинается с позиции, кратной четырем). А уж затем в окончательном результате использовать нормальный LIKE PREDICATE.

Или, как уже говорили, просто и незатейливо добавлять к каждому символу суффикс и затем использовать full-text phrase match (двойные кавычки). Скорее всего, придется использовать TEXT datatype.
Увидев друга, Портос вскрикнул от радости...
Ответить

Вернуться в «Вопросы и новости IT»