SQLinfo.ru - Все о MySQL

Форум пользователей MySQL

Задавайте вопросы, мы ответим

Вы не зашли.

#1 15.10.2012 19:45:07

yuriy
Завсегдатай
Зарегистрирован: 24.10.2010
Сообщений: 76

Проэктирование поиска в базе данных

Привет, всем!!!
Пдскажите, пожалуйста. Есть задача создать поиск в базе данных (на данный момент в СУБД - MySQL).
Планируеться поиск проводить по загружаемых прайсах. Каждый прайс содержит около 10 тис. наименований. Разумется таких прайсов будет сотни, отчего размеры таблиц будут очень большими (свыше десятка миллионов строк, а то и больше).
Использовать преславутую технологию поиска, в частности FULLTEXT для движков MyISAM - есть сомнительное занятие.
Может быть, кто-то из вас знает лучший подход (за исключением Sphinx), который будет позволять быстро и реллевантно искать товары в огромных таблицах.
Буду признателен за любой совет!!!

Неактивен

 

#2 15.10.2012 20:15:43

Shopen
Гуру
Откуда: Москва
Зарегистрирован: 22.10.2007
Сообщений: 362

Re: Проэктирование поиска в базе данных

Почему использование fulltext - сомнительное занятие?
И в каком смысле поиск по прайс-листам, какие критерии поиска ожидаются?

Неактивен

 

#3 15.10.2012 22:21:58

yuriy
Завсегдатай
Зарегистрирован: 24.10.2010
Сообщений: 76

Re: Проэктирование поиска в базе данных

Планируется организовать поиск по таким критериям: по наименованию товара и по его артиклю, по группе товаров и может быть еще ряд фильтров добавятся. Просто если таблица будет насчитывать десятки а может и сотни миллионов строк - как быстро будет производиться поиск среди такого множество строк в случаее использования - fulltext? Как лучше создать все это чтобы производительность была максимальной?

Отредактированно yuriy (15.10.2012 22:22:37)

Неактивен

 

#4 16.10.2012 18:37:34

Shopen
Гуру
Откуда: Москва
Зарегистрирован: 22.10.2007
Сообщений: 362

Re: Проэктирование поиска в базе данных

Лучше всего сделать проект БД, запонить его сгенерированным правдоподобным контентом и потестировать. Если выбранное решение не соответствует нужным критериям, например скорости - искать другое решение или модифицировать существующее (оптимизация, денормализация, партиционирование и т.п.). А на этапе идеи (я так понимаю у вас именно этот этап) обсуждать инструменты как то рановато.

Например я не очень себе представляю зачем нужен полнотекстовый поиск по прайс-листам, обычно ищут по артикулу (LIKE '112-13%'), по названию модели(опять же левый лайк) или по разным там категориям и характеристикам (которые как правило хранятся в отдельных полях БД). А полнотекст зачем? Возможно у вас будут статьи, в которых будет нужен поиск названий моделей? А статей тоже будет миллионы?

Может быть fulltext вам действительно нужен, просто вы забыли рассказать про задачу поподробнее. Так что сомнительное занятие - это заниматься такой вот теорией.

Неактивен

 

#5 16.10.2012 19:21:21

yuriy
Завсегдатай
Зарегистрирован: 24.10.2010
Сообщений: 76

Re: Проэктирование поиска в базе данных

Задача стоит в следующем. Планируется создать поиск по прайсам, которые будут загружать продавцы автозапчастей. Поиск соответственно будет происходить по названию запчасти и по коду. Вопрос: все загружаемые прайсы где сохранять: в одной большой таблице или для каждого прайса создавать новую таблицу (в этом случае  база данных будет насчитывать 1000 табл. или более табл., что как мне кажется не есть хорошо). А с другой стороны если все прайсы сливать в одну табл. кол-во записей достигнет огромных значений (порядка 30-50 мил строк).
И еще вопрос: как в таком случае лучше организовать поиск (использовать LIKE (на огромных данных не подходит), fulltext или что-то другое)?

Отредактированно yuriy (16.10.2012 19:26:34)

Неактивен

 

#6 17.10.2012 12:54:29

Shopen
Гуру
Откуда: Москва
Зарегистрирован: 22.10.2007
Сообщений: 362

Re: Проэктирование поиска в базе данных

Уважаемый Юрий. Убедительная просьба хоть как то аргументировать ваши высказывания

Использовать преславутую технологию поиска, в частности FULLTEXT для движков MyISAM - есть сомнительное занятие

основания так утверждать?

Может быть, кто-то из вас знает лучший подход (за исключением Sphinx)

почему кроме сфинкса?

использовать LIKE (на огромных данных не подходит)

почему не подходит?

специально для вас сделал табличку

CREATE TABLE `big` (
  `uuid` char(32) NOT NULL,
  KEY `uuid` (`uuid`)
) ENGINE=MyISAM DEFAULT CHARSET=cp1251;


В ней 80 млн строк, 40 сгенерированных, потом удвоена самокопированием, т.е. строки не уникальны

SELECT * FROM big WHERE uuid LIKE '8fa%'

--> 19902 rows fetched (94 ms)

SELECT * FROM big WHERE uuid LIKE '8F000042-3D62-45BA-BF1D-9FFD56CB'

--> 2 rows fetched (0 ms)

в случае уникального ключа (а артикул должен быть именно таким) будет еще быстрее.

1000 таблиц - это ерунда, никаких проблем не будет, по сути проблемы возникнут только если количество файлов приблизится к сотням тысяч (для файловой системы это будет тяжело, не для mysql)

Но я бы в вашем случае думал про партиционирование - http://dev.mysql.com/doc/refman/5.1/en/ … oning.html

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

Неактивен

 

#7 19.10.2012 12:31:30

yuriy
Завсегдатай
Зарегистрирован: 24.10.2010
Сообщений: 76

Re: Проэктирование поиска в базе данных

С партиционированием немного разобрался. Но вот как-то не пойму, как правильно ораганизовать разбиение таблицы. Задача в следующем:
Как уже говорил, есть таблица прайсов. Структура ее, к примеру выглядит так:

-----------------------------------------------------------
id | название товара    | код товара    | id-пользователя |
-----------------------------------------------------------
27| Цемент                 | 02E325025AD |          123          |
----------------------------------------------------------
28| Гвозди                  | 3D0616040Q  |          123          |
----------------------------------------------------------
29| Цемент                 | 02E325025AD |          127          |
----------------------------------------------------------
30| Гвозди                  | 3D0616040Q  |          127          |
----------------------------------------------------------
...|  ...                       |  ...               |  ...
---------------------------------------------------------|
99| Цемент                 | 3D0616040Q   |          257         |
-----------------------------------------------------------

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

Поиск планируется производит по названию товара и его коду. Может быть в дальнейшем прикрутим фильтр еще по регионам, цене...
При выборке должно отобразится все товары которые соответствуют запросу.
Таблица соответственно планируется быть огромной - десятки миллионов строк.

Как правильно построить (разбить) таблицу чтобы поиск был максимально эффективным в плане скорости и реллевантности?
Посоветуйте, пожалуйста, по какому критерию лучше разбивать табл. и какой способ разбиения применить (RANGE, HASH, KEY).
Или может быть здесь разбиение и не нужно....
Спасибо за любую подсказку...!!!

Неактивен

 

#8 20.10.2012 01:27:31

yuriy
Завсегдатай
Зарегистрирован: 24.10.2010
Сообщений: 76

Re: Проэктирование поиска в базе данных

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

-----------------
"Надо понимать - что я все это писал про поиск по начальным символом а не LIKE'о-образный поиск по середине кода. С lik'ом при десятках миллионов ничего не поможет.
Так что имея первые 2 буквы - вы уже всегда на клиенте знаете в какую из таблиц полезть за результатами.

Например есть у Вас 10 млн. наименований вида(для примера):

RPLJ-04FGK_F10
A180-103

Вы перед вставкой думаете - ага, на A у меня начинается 835 536, а на B 143 654 наименований.
Делаете таблицы

AA AB AC .....

BA BB BC .....

Как правило на второй букве уже можно ограничиться т.к. там уже буду тысячи, максимум десятки тысяч записей.

Как работает LOCK на myIsam? Он открывает файл, и лочит его на уровне ФС. Так что каждое обращение будет открывать, допустим гигабайтный файл, что-то искать и закрывать - это само по себе очень долго т.к. файл при открытии перемещается в ОП.
На INNODB получше но забудьте про FULLTEXT.
Итак, на этом этапе у Вас есть допустим ~900 небольших таблиц которые лочатся при запросах отдельно.

Помимо этого есть как я уже писал такая вещь как hash индексы разной длины как неплохая альтернатива полнотекстовым.

Т.е. например вы дальше имея 900 таблиц строите по каждой hash-индексы по 1 букве.

Дальше пользователь начинает вводить например:
A18, система уже знает что из таблички(физического файла) "A1", ей надо отфильтровать только ту часть которая соответствует выборке по индексу "8" - и весь этот набор перегружается во временную таблицу(либо в зависимости от частоты система уже заранее построила вам hash-индекс по двум буквам 1A, 1B.... и если пользователь ввел всего не A18 а A184 то уже используется этот hash-индекс).

"

Отредактированно yuriy (20.10.2012 11:17:12)

Неактивен

 

#9 21.10.2012 20:14:17

evgeny
Гуру
Зарегистрирован: 04.05.2009
Сообщений: 335

Re: Проэктирование поиска в базе данных

А чем вам Sphinx не угодил ?

Неактивен

 

#10 21.10.2012 22:37:32

yuriy
Завсегдатай
Зарегистрирован: 24.10.2010
Сообщений: 76

Re: Проэктирование поиска в базе данных

Сложный очень.... хочеться развить данную идею изложену высше... может кто-то поможет разобраться с построением поисковых промежуточных таблиц для организации быстрого поиска по больших таблицах данных...

Отредактированно yuriy (21.10.2012 23:13:30)

Неактивен

 

#11 22.10.2012 14:40:24

Shopen
Гуру
Откуда: Москва
Зарегистрирован: 22.10.2007
Сообщений: 362

Re: Проэктирование поиска в базе данных

yuriy написал:

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

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

aa1021**
aa1022**
ab1042**
ab204**
...
zx0623j**

и т.п.

то вы разбиваете полную базу на таблицы AA_, AB_, ... ZX_ в которые кладете товары с соответствущими артикулами. Когда пользователь ищет допустим abd1042gr_sta - то ваш скрипт ищет не по всей базе, а только по таблице AB_.

Честно говоря - идея спорная, т.к. по сути это альтернативная реализация индекса (или партиционирования). Если по полю артикула у вас есть индекс - то mysql (я приводил пример выше) и так быстро найдет нужную запись.

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

Насчет hash индекса я не очень понял, что вам советовали. И зачем, если после разбиения в таблицах остаются десятки тысяч строк - оно и так будет пулей работать...

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

Юрий, хочется вас спросить - какие способы вы уже попробали практически?

Приведите пример реального набора данных, объем, DLL ваших таблиц и замеры скорости типовых запросов с указанием мест где тормозит?

Неактивен

 

#12 22.10.2012 16:44:49

yuriy
Завсегдатай
Зарегистрирован: 24.10.2010
Сообщений: 76

Re: Проэктирование поиска в базе данных

Спасибо за детальную интерпертацию... согласен с вами с тем что "геморно такие структуры поддерживать, там и кодировки могут всплыть, т.к. артикулы могут оказаться (внезапно) с русскими буквами и пр." - такой вариант не подходит!!!
Сейчас занимаюсь партиционированием таблиц для поиска по каталогу.
Суть в следующем.
Таблицы группируются, к примеру, по группе товара (запчастей) - создается 30 таблиц.
Каждый прайс будет загружаться в одну из этих таблиц, соответственно по тематике и соответствию номенклатуры запчасти которая относится к той или инной группе.
Затем каждую из этих 30 таблиц планируется разбить на секции (разделы) по критерию марки авто.
Исходя из всего этого мы сужуем диапазон поиска - сразу по двух критериях - группа запчасти и марка авто.
Если к примеру, пользователь выбирает Марку (ВАЗ) - Модель (21099) - Группа запчасти (Фильтры) - то система ищет соответственно в табл. которая относиться к группе (Фильтры) - затем находит подраздел в этой же таблице по марке ВАЗ - и выдает весь результат.
Думаю такой алгоритм будет быстро искать по каталогу не перегружая систему огромными таблицами (в десятки мил. строк).
Если будут какие-либо замечание - прошу высказываться... зарание всем спаибо за участие в проэктировании...

Но вот организовать поиск по артиклу (коду товара) по такой структуре пока неясно!!! Хочеться создать одновременно и поиск по каталогу и поиск по коду товара.
Я пока не тестировал поиск по LIKE% - как будут каие-то результаты сообщу вам.

Неактивен

 

#13 22.10.2012 17:16:35

Shopen
Гуру
Откуда: Москва
Зарегистрирован: 22.10.2007
Сообщений: 362

Re: Проэктирование поиска в базе данных

yuriy написал:

Я пока не тестировал поиск по LIKE% - как будут какие-то результаты сообщу вам.

будем ждать. да, и пожалуйста - проектирование

Неактивен

 

#14 22.10.2012 19:54:13

yuriy
Завсегдатай
Зарегистрирован: 24.10.2010
Сообщений: 76

Re: Проэктирование поиска в базе данных

Значит так:
Создал таблицу на сервере и на локальной машине для тестирования из трех полей:

------------------------------------
id  |  namezapch  | numberkatalog  |
------------------------------------
Напхал туда 4 имл. строк и с помощью лайк сделал выборку:

SELECT * FROM pric WHERE numberkatalog LIKE  '038253010C';

На сервере показало: Отображает строки 0 - 29 ( 2,595 всего, Запрос занял 0.04 сек.)
На локальной машине: 3498 rows in set (0.56 sec)
Судя по показателем неплохо!!! На сервере даже быстрей выполняется нежели на локальной машине)))
Правда если туда добавить 100 мил. строк, может быть время составит порядка 1-2 сек.

Получаеться, что всю информацию можно хранить в одной огромной таблице (размером порядка 100-200 мил. строк) и LIKE-ом производить поиск товаров.
Кстати поле по LIKE нужно проиндексировать?
Кроме этого весь этот запрос можно написать в хранимых процедурах, так оно еще быстрей будет искать? Верно?


Судя из проведенных тестов партиционирование не нужно теперь!

Отредактированно yuriy (22.10.2012 19:58:10)

Неактивен

 

#15 23.10.2012 08:07:45

vasya
Архат
MySQL Authorized Developer
Откуда: Орел
Зарегистрирован: 07.03.2007
Сообщений: 5833

Re: Проэктирование поиска в базе данных

yuriy написал:

Кроме этого весь этот запрос можно написать в хранимых процедурах, так оно еще быстрей будет искать? Верно?

Нет. Серверу MySQL без разницы откуда пришел запрос - от скрипта php, хранимой процедуры или удаленного терминала.

Неактивен

 

#16 23.10.2012 10:02:24

yuriy
Завсегдатай
Зарегистрирован: 24.10.2010
Сообщений: 76

Re: Проэктирование поиска в базе данных

Таблица получается очень большая, поэтому есть желание ее разбить. Скжите, как ведет себя LIKE когда таблица разделена на секции (подтаблицы - партиционирование)?

Отредактированно yuriy (23.10.2012 10:03:04)

Неактивен

 

#17 23.10.2012 13:08:55

yuriy
Завсегдатай
Зарегистрирован: 24.10.2010
Сообщений: 76

Re: Проэктирование поиска в базе данных

vasya написал:

yuriy написал:

Кроме этого весь этот запрос можно написать в хранимых процедурах, так оно еще быстрей будет искать? Верно?

Нет. Серверу MySQL без разницы откуда пришел запрос - от скрипта php, хранимой процедуры или удаленного терминала.

Почему же: если скажем приходиться делать несколько запросов (выборка данных из большой табл. и затем результат поместитье у временную таблицу) - так будет быстрей - откомпилированый код на самом сервере выполняется намного быстрее нежжели из рнр-сценария создавать несколько запросов!!!

Неактивен

 

#18 23.10.2012 15:05:24

vasya
Архат
MySQL Authorized Developer
Откуда: Орел
Зарегистрирован: 07.03.2007
Сообщений: 5833

Re: Проэктирование поиска в базе данных

yuriy написал:

Почему же: если скажем приходиться делать несколько запросов (выборка данных из большой табл. и затем результат поместитье у временную таблицу) - так будет быстрей

А какая разница откуда делать эти несколько запросов - из скрипта php, хранимой процедуры или удаленного терминала?

yuriy написал:

откомпилированый код на самом сервере выполняется намного быстрее нежжели из рнр-сценария создавать несколько запросов!!!

Это вы о чем? Что такое "откомпилированый код"? Prepared statement? Так, во-первых, не намного быстрее, а, во-вторых, живут они в течении сессии, и какая разница что за сессия - скрипта php, хранимой процедуры или удаленного терминала?

Неактивен

 

#19 23.10.2012 15:25:31

Shopen
Гуру
Откуда: Москва
Зарегистрирован: 22.10.2007
Сообщений: 362

Re: Проэктирование поиска в базе данных

yuriy написал:

Значит так:

SELECT * FROM pric WHERE numberkatalog LIKE  '038253010C';

На сервере показало: Отображает строки 0 - 29 ( 2,595 всего, Запрос занял 0.04 сек.)
На локальной машине: 3498 rows in set (0.56 sec)
Судя по показателем неплохо!!! На сервере даже быстрей выполняется нежели на локальной машине)))
Правда если туда добавить 100 мил. строк, может быть время составит порядка 1-2 сек.

Кстати поле по LIKE нужно проиндексировать?

Судя из проведенных тестов партиционирование не нужно теперь!

1. В данном случае вы хоть и написали LIKE, но по сути ваш запрос равен такому:

SELECT * FROM pric WHERE numberkatalog =  '038253010C'

проверяйте лучше именно по LIKE '03825%' если конечно поиск по части артикула у вас будет вообще. Если только точный поиск, то бинго

2. Судя по количеству возвращенных строк - у вас не особо артикулы уникальны (2500 позиций  с артикулом "038253010C" плохо похоже на реальность).

3. А у вас запрос выше работает без индекса на поле `numberkatalog` с такой скоростью?? Индекс безусловно нужен. Он нужен по всем полям упоминающихся во WHERE при наличии достаточной селективности.

4. Процедуры в данном случае - это экономия на спичках

Неактивен

 

#20 23.10.2012 16:12:14

yuriy
Завсегдатай
Зарегистрирован: 24.10.2010
Сообщений: 76

Re: Проэктирование поиска в базе данных

Shopen написал:

1. В данном случае вы хоть и написали LIKE, но по сути ваш запрос равен такому:

SELECT * FROM pric WHERE numberkatalog =  '038253010C'

проверяйте лучше именно по LIKE '03825%' если конечно поиск по части артикула у вас будет вообще. Если только точный поиск, то бинго

2. Судя по количеству возвращенных строк - у вас не особо артикулы уникальны (2500 позиций  с артикулом "038253010C" плохо похоже на реальность).

3. А у вас запрос выше работает без индекса на поле `numberkatalog` с такой скоростью?? Индекс безусловно нужен. Он нужен по всем полям упоминающихся во WHERE при наличии достаточной селективности.

4. Процедуры в данном случае - это экономия на спичках

----------------------------------------
Иксать у меня будет по коду товара - строгое совпадение:
SELECT * FROM pric WHERE numberkatalog =  '038105264J';
По названию с выражением LIKE%
SELECT * FROM pric WHERE namezapch LIKE  'бампер%';

1. Вы правы, количество возвращенных строк по артикулах не уникальны, потому что одни и те же товары (их коды и название) в разных прайсах одинаковы. Продавцы загружают прайсы в которых продают одни и те же товары (они совпадают). Как здесь быть? Наверное никак...!!!
2. Индексы проставил по названиях и по их коду.
Делаю запрос по названию товара на сервере в phpMyAdmin - кол-во строк 4 мил. записей:

SELECT * FROM pric WHERE namezapch LIKE  'бампер%';

Результат:
Отображает строки 0 - 29 ( 49,287 всего, Запрос занял 0.0004 сек.)
Время сдесь сомнительное - поэтому по моим наблюдением запрос выполняется где-то около 1-2 сек.

3. Есть идея следущего характера:
Разбить огромную таблицу на разделы, по критерию марки автомобилей.
При этом, диапазон выборки значительно уменьшится. Предположим, пользователь ищет бампер (при этом он должен обязательно укзать марку авто).
MySQL будет в таком случае искать название товара не по всей огромной табл. а по раздулу марки к которой относиться данный товар.
Как Вы считаете такой подход будет оправданным или нет?
Спасибо!

Отредактированно yuriy (23.10.2012 16:46:56)

Неактивен

 

#21 23.10.2012 17:19:31

Shopen
Гуру
Откуда: Москва
Зарегистрирован: 22.10.2007
Сообщений: 362

Re: Проэктирование поиска в базе данных

Юрий, вы меня утомили smile

Разбейте таблицу, ради бога, раз она вам не нравится, диапазон уменьшится, количество запросов вырастет в N раз (сколько таблиц, столько запросов). Что в сумме окажется быстрее - вопрос спорный, замеряйте 1 запрос c бампером к одной таблице, замеряйте суммарное время 50-60 запросов к табличкам и сравните. (но я думаю что второй вариант медленнее)

0.0004 сек на 4 млн строк по индексу - очень похоже на правду. Но может быть это кэширование работает, если запрос не первый раз сделан. Дописывайте в запросы "SELECT SQL_NO_CACHE ..."  или что то типа AND 2=2, чтобы кэширование не использовалось

Большая часть вопросов которые вы задаете - проверяется самостоятельно довольно быстро. Вам не дадут здесь готовую архитектуру БД, тем более не зная конкретно ваших данных и задач.

Отредактированно Shopen (23.10.2012 17:52:09)

Неактивен

 

#22 23.10.2012 19:43:28

yuriy
Завсегдатай
Зарегистрирован: 24.10.2010
Сообщений: 76

Re: Проэктирование поиска в базе данных

Спасибо за консультацию!!!!

Неактивен

 

Board footer

Работает на PunBB
© Copyright 2002–2008 Rickard Andersson