imho.ws |
![]() |
![]() |
![]() |
# 1 |
Full Member
Регистрация: 29.05.2002
Сообщения: 544
![]() ![]() ![]() ![]() ![]() |
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), выделенный сервер.
__________________
убрано по просьбе администратора ![]() |
![]() |
![]() |
# 2 |
МОД-Оператор ЭВМ
Регистрация: 18.04.2002
Адрес: Питер
Сообщения: 4 343
![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() |
Какой справедлив порог ... а какие у тебя данные? Если ты собрался ездить LIKE'ом по полю LONGTEXT, то это одно, а если по VARCHAR, то совсем другое.
Вообще LIKE никогда быстрым не был и использовать его для больших таблиц крайне нежелательно. Мне одно неясно, - каким боком заказчика не устранивает полнотекстовый поиск? |
![]() |
![]() |
# 3 |
Full Member
Регистрация: 29.05.2002
Сообщения: 544
![]() ![]() ![]() ![]() ![]() |
Ну смотри. Он хочет чтобы было так:
Поле ввода. ввожу «nok», например. Должен быть произведен поиск по всем категориям товаров(обработка логики и т.д.). Ясно, что в «сотовых телефонах» скорее всего будет «nokia», и пользователь должен получить список телефонов и/или других товаров, которые содержат в определенных полях последовательность символов «nok». Кроме того, полнотекстный поиск не ищет(по-умолчанию) слова меньше 4 символов, т.е. тот же телефон «lg» найден не будет.
__________________
убрано по просьбе администратора ![]() |
![]() |
![]() |
# 4 |
Full Member
Регистрация: 29.05.2002
Сообщения: 544
![]() ![]() ![]() ![]() ![]() |
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 но это уже получается полуинддекс ![]() вобщем, есть над чем подумать...жду ценных идей и предложений. p.s. random avatars не рулит ![]() p.p.s. изменения на форуме, я так понимаю — результат работы новой команды разработчиков «форума ИМХО»? ![]()
__________________
убрано по просьбе администратора ![]() Последний раз редактировалось Sheryld; 01.04.2005 в 17:17. |
![]() |
![]() |
# 5 |
Full Member
Регистрация: 29.05.2002
Сообщения: 544
![]() ![]() ![]() ![]() ![]() |
ну кстати 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%" но в новой таблице запрос выполняется за: 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; 04.04.2005 в 17:52. |
![]() |
![]() |
# 6 |
Full Member
Регистрация: 29.05.2002
Сообщения: 544
![]() ![]() ![]() ![]() ![]() |
все-таки решил испробовать задумку с хранением не только отдельных слов, но и частей слов.
вот что получилось: реальный запрос, поиск телефона 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); } } есть еще идея попробовать полнотекстный поиск по такой таблице и сравнить его с like, но думаю именно такой like будет быстрее. кстати, кто может сказать, что лучше: хранить текст в одной записи, типа: это большой кусок текста (text) или хранить его типа: это (varchar) большой кусок текста при том, что используется полнотекстный индекс и поиск?
__________________
убрано по просьбе администратора ![]() |
![]() |