IMHO.WS

IMHO.WS (http://www.imho.ws/index.php)
-   Веб-программирование (http://www.imho.ws/forumdisplay.php?f=29)
-   -   Mysql like запросы(+) (http://www.imho.ws/showthread.php?t=82887)

Sheryld 31.03.2005 11:48

Mysql like запросы(+)
 
Какой порог в плане объема данных(размера таблицы) справедлив для mysql сервера, чтобы получить выборку за приемлемое время.

Запросы в основном типа:
select count(*) ... like ...
select ... like ... limit ... (т.е. разбивка на страницы)
select ... joins ... like ... limit

p.s. возникла проблема построения поиска по базе с прайс-листами, полнотекстный поиск заказчика не устраивает.

размер таблицы может достигать 100к записей. реально ли использовать like на таких таблицах? или же стоит все-таки отказаться от этой идеи?

p.p.s. сервер mysql 3.23.58(freebsd), выделенный сервер.

RaZEr 31.03.2005 13:57

Какой справедлив порог ... а какие у тебя данные? Если ты собрался ездить LIKE'ом по полю LONGTEXT, то это одно, а если по VARCHAR, то совсем другое.

Вообще LIKE никогда быстрым не был и использовать его для больших таблиц крайне нежелательно. Мне одно неясно, - каким боком заказчика не устранивает полнотекстовый поиск?

Sheryld 31.03.2005 14:13

Ну смотри. Он хочет чтобы было так:

Поле ввода. ввожу «nok», например.

Должен быть произведен поиск по всем категориям товаров(обработка логики и т.д.). Ясно, что в «сотовых телефонах» скорее всего будет «nokia», и пользователь должен получить список телефонов и/или других товаров, которые содержат в определенных полях последовательность символов «nok».

Кроме того, полнотекстный поиск не ищет(по-умолчанию) слова меньше 4 символов, т.е. тот же телефон «lg» найден не будет.

Sheryld 01.04.2005 17:15

hint:

если искать не любые совпадения типа: like "%kwrds%", а свопадения с началом строки, типа:

like "kwrds%" да еще и с индексом поиграться, то получается вполне прилично, на таблице со 100к записей результат count будет порядка 0.05-0.06 ms.

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

"nokia 2600"

"nok" он найдет, а вот 2600 уже нет, возможно кнечно кажую позицию сплитить, т.е.

table price
p_id

table split_price
sp_id
p_id (FK)
word

но это уже получается полуинддекс:) и придется делать join.

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

p.s. random avatars не рулит:(
p.p.s. изменения на форуме, я так понимаю — результат работы новой команды разработчиков «форума ИМХО»?:)

Sheryld 04.04.2005 18:19

ну кстати fulltext search не такой уж и быстрый. на 110 к записей поиск по часто встречающемуся слову(23к. раз) занимает примерно секунду(или даже больше — точно не помню уже). Это только count.

машинка:

athlon xp 1700+
512 ram ddr
mysql 3.23.58 d-max-nt under windows xp sp 2 beta

я придумал немного другое решение. но оно пока еще «сыровато». смысл такой:

1. все фразы разбиваем на слова(выкидываем предлоги и прочую муть).
2. записываем в таблицу(примерную структуру я описал выше).
3. создаем индекс(обычный) на поле со словом.
4. ищем только запросами типа like "kwrds%".

допустим было:

sonyericsson t620 se

pid pword
1 sonyericsson
1 t620
1 se

запрос будет такой:

Код:

SELECT count( * )
FROM price_word
as pw1
inner join price_word
as pw2
on pw1.pid = pw2.pid
inner join price_word
as pw3
on pw2.pid = pw3.pid
where pw1.pwword
like "sony%"
and pw2.pwword
like "se%"
and pw3.pwword
like "t630%"

идея примерно такая. что делать дальше — пока хз.
нужно сделать вот еще что:

каждое слово должно иметь n-представлений, где n=(wordlen-(minSearchWordLen)-1).

пример:

sonyericsson
onyericsson
nyericsson
yericsson
ricsson
icsson
sson

при minSearchWordLen = 4

поиск идет очень быстро, но конечно, если текста очень много данный вариант не пройдет:)

хотя последнее можно на любителя, т.к. мало кто не способен написать первые три-четрые буквы того, что ищет.

p.s. все вышесказанное относится конечно к специфическому(моему) случаю, когда нужно осуществлять поиск по базе с товарами(по большей части техника).

это был поиск в пределах одной записи(прайс-листа).

а как сделать поиск типа or — еще проще:


Код:

SELECT count( * )
FROM price_word
as pw1
where pw1.pwword
like "nok%"
or pw1.pwword
like "sam%"

у меня поулчается 45к.

но в новой таблице запрос выполняется за:

0.09 sec.

а в старой(это если хранить запись прайс-листа целиком), и тогда запрос будет:

Код:

SELECT count( * )
FROM price_word
as pw1
where pw1.pwword
like "%nok%"
or pw1.pwword
like "%sam%"

время выполнения:

0.27-0.30 sec.

т.е. в 3 раза медленее!

Sheryld 05.04.2005 18:36

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

вот что получилось:

реальный запрос, поиск телефона Samsung d500(точнее подсчет предложений в базе по этому телефону(чтобы было посложнее, я добавил побольше ключевых слов).
Код:

SELECT count(distinct sci.str_cat_itm_ID) as cnt FROM store_pword as sw0 inner join store_pword as sw1 on sw0.str_cat_itm_ID = sw1.str_cat_itm_ID inner join store_pword as sw2 on sw1.str_cat_itm_ID = sw2.str_cat_itm_ID inner join store_pword as sw3 on sw2.str_cat_itm_ID = sw3.str_cat_itm_ID inner join store_category_item as sci on sw0.str_cat_itm_ID = sci.str_cat_itm_ID inner join store_category as sc on sci.str_cat_ID = sc.str_cat_ID where sc.str_cat_END_DATE>=1112712382 and sw0.str_PWORD like 'sung%' and sw1.str_PWORD like 'd500%' and sw2.str_PWORD like 'sgh%'
время выполнения запроса:
0.14 sec.(запрос помещен в файл и вызывается из консоли).

результат: 1000 записей.

теперь аналогичный запрос, но поиск обычным like:

Код:

SELECT count(sci.str_cat_itm_ID) as cnt FROM store_category_item as sci inner join store_category as sc on sci.str_cat_ID = sc.str_cat_ID where sc.str_cat_END_DATE>=1112712382 and sci.str_cat_itm_TITLE like '%sung%' and sci.str_cat_itm_TITLE like '%d500%' and sci.str_cat_itm_TITLE like '%sgh%'
время выполнения запроса:
0.25-0.27 sec.

результат: 1000 записей.

размеры таблиц:

store_category_item: 110.000
store_pword: 657.000

размер минимальной словоформы - 4 символа, т.е. в поиске я еще не ввел это ограничение, но ввел его при индексации, т.е. например:

если слово меньше или равно 4, то мы вносим его как есть в таблицу store_pword, если больше 4, тогда:

Код:

if ($wordLen >= 3)
{
        for($i=0;$i<$wordLen-3;$i++)
        {       
                //insert
                substr($titleWord,$i);                                                                                                                                                                               
        }                                               
}

p.s.

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

кстати, кто может сказать, что лучше:
хранить текст в одной записи, типа:
это большой кусок текста (text)
или хранить его типа:
это (varchar)
большой
кусок
текста

при том, что используется полнотекстный индекс и поиск?

Kvarx 15.08.2006 21:39

А как сделать запрос, который будет в таблице во всех текстовых полях искать текст.

Вроде так нельзя, но как-нибудь похоже можно, что все поля не перечислять?
SELECT * FROM table WHERE * LIKE '%$text%'

RaZEr 15.08.2006 21:52

Никак. Либо full-text search либо перечислять. Хотя можно сделать колонку-индекс и искать по ней.

Kvarx 16.08.2006 12:11

В смысле колонку индекс? Отдельную таблицу с словом и его индексом? Запрос разбивать на слова и искать эти слова. Или что-то другое?

А что означает full-text search?


Часовой пояс GMT +4, время: 12:20.

Powered by vBulletin® Version 3.8.5
Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.