Оптимизация очень большой базы для поиска

Black Rabbit

Новичок
Оптимизация очень большой базы для поиска

Всем привет!
Помогите пожалуйста решить проблему
Есть база данных продукции, каждый продукт помимо общих для всей продукции свойств (цена, название. фото) обладает собственным набором характеризующих его параметров. Эти параметры сгруппированы по категориям, их число не фиксировано. Что-то вроде http://market.yandex.ru/model.xml?hid=9149...;modelid=898029, только конечно намного примитивнее

Структура базы примерно такова

products: (например Siemens C75)

id - уникальный айди продукта
price - цена
..... - прочие параметры
options - категория, из которой данный продукт считывает свойства (options_categories.id )


options_categories

id - уникальный айди категории
title - название категории (например мобильные телефоны)

options

id - уникальный айди своиства
cat_id - айди категории (options_categories.id )
title - название свойства (например Тип корпуса)
type - тип своиства (чекбокс, селектбокс, текстбокс)
search - флаг, указывающий использовать ли данное свойство для поиска по продукции


options_filled

pid - айди продукта (products.id )
oid - айди свойства (options.id )
value - чему равно у данного продукта данное свойство

Если речь идет просто об отображении информации о конкретном продукте или списка продукции,
такая организация работает на ура. Проблемы возникают на этапе поиска

На основании таблицы options генерируется поисковая форма, выборка идет из options_filled
Запрос поступает из формы в виде набора пар oid - value
Array
(
[26] => n
[29] => 10
[33] => 0
)

После чего делаю запрос примерно такого вида

select* from options_filled where (oid='26' and value='0') or (oid='29' and value>='10') or (oid='33' and value='0') group by oid,pid

Таблица options_filled может содержать свыше 700 000 записей.... Предыдущий запрос всего лишь на 119,232 выполнялся 0.35 сек.... Можно ли как-то оптимизировать поиск?
У меня есть идея сделать индексацию базы - написать скрипт, который будет раз в несколько дней выгребать инфу и раскладывать ее по другим таблицам, например для каждой категории создавать свою таблицу и выгребать в нее только те свойства, по которым должен идти подбор. Интересно, делает так кто-нибудь?
 

alexhemp

Новичок
Вот тут мы такую задачу решали

http://phpclub.ru/talk/showthread.php?s=&threadid=65869

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

В твоем случае сделать можно быстро даже на MySQL 3.2.x которую сейчас днем с огнем :)
 

Black Rabbit

Новичок
Делаю почти так же, индексы стоят. Результат теста неутешительный - на миллион записей время выполнения запроса приблизительно 1,4 секунды
 

Krishna

Продался Java
Как минимум, двойной индекс по (options_filled.oid, options_filled.value)
 

Black Rabbit

Новичок
Когда ставлю двойной индекс, тормозит еще больше
На 100 000 записей
индекс по полям (oid, value) - выборка идет за 0,2 сек
индекс только на oid - то за 0,39 сек
без индексов - 0,15 сек
 

bubblegum

Новичок
Я делал проще (для поиска по строке, а не подбор по параметрам)
в товары поле forsearch, в него проходимся по базе и складываем название, артикул, все характеристики через пробел. На это поле fulltext index. Названия характеристик - по желанию (можно сложить в поле, можно - только значения, я клал название свойств); название товара - 2 раза (для изменения релевантности - например для поиска "ноутбук" впереди д/б товар "ноутбук", а уж потом мыши с характеристикой "назначение - ноутбук" )

Для подбора по параметрам для каждого параметра делаем запрос и формируем для запроса_по_товарам where товар_id in (), но мне проще - есть ограничение по разделу каталога.

В базе 30К товаров, почти млн характеристик; время не замерял но не тормозит
 

Krishna

Продался Java
Black Rabbit
Пардон, я видимо не догнал, если ты в результате извлекаешь 119,232 строк из 700,000 (если я правильно понял), то так и должно быть. Быстрее полного скана тут не получится.

-~{}~ 10.12.06 13:38:

Когда ставлю двойной индекс, тормозит еще больше
На 100 000 записей
индекс по полям (oid, value) - выборка идет за 0,2 сек
индекс только на oid - то за 0,39 сек
P.S.
Нелады с арифметикой? 0,2 в 2 раза меньше, чем 0,39

Двойной индекс здесь не может быть хуже одинарных.
Но может быть хуже отсутствия. Индекс реально начинает работать на ускорение, когда он служит для выборки < 2% строк
 

Black Rabbit

Новичок
Krishna, вначале тестировалось на 119,232 записях , потом увеличила до миллиона

-~{}~ 10.12.06 13:59:

bubblegum, к сожалению мне надо точно по параметрам
 

bubblegum

Новичок
У тебя есть каталогизатор товаров ?
у меня так:
.. считаем что форма подбора уже нарисована..
1 имеем кат_ид - раздел каталога.
2 получаем из формы список значений параметров массивом
3 делаем запрос на список товаров разделе, получаем строку where товар_ид in (555,556,...)
sql_по_товарам.=" and (0 "
далее по каждому параметру:
4 для набора чекбоксов: select distinct (товар_ид) from options_filled where pid in(п.3) and value in (implode(',',из_формы
->sql_по_товарам.=" or товарс_ид in(implode(getCol(sql_по_свойствам)
для хтмл_селект то же самое только value=из_формы
...
}
sql_по_товарам.=")"

написал упрощенно; еще есть проверки
получается дофиг запросов, но работает влёт
 

Black Rabbit

Новичок
Да, товары разложены по разделам, например 'квартиры на продажу', 'квартиры на сдачу', 'машины'. Отдельно имею дерево категорий для свойств - к примеру категория 'квартиры', в эти категории добавляются свойства, для каждого свойства указываю его тип - отображать его как чекбокс, листбокс или текстовое поле, а также указываю надо ли этот параметр учитывать для поиска. Все происходит в визуальном режиме через админку сайта.
При добавлении нового продукта, сперва указываю из какой категории ему считывать свойства - то есть в базе имею id продукта , id категории и id категории параметров. Затем выгребаю из таблицы параметров те, которые относятся к указанной категории, формирую из них форму, заполняю и записываю в options_filled .
На сайте эти параметры используются и для поиска, и как описание продукта.
Если речь идет о поиске, выбираю только поисковые параметры и формирую таблицу для подбора товара - в качестве названий полей формы использую айдишки

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

Думаю, все-таки сделаю индексатор - options_filled буду разбивать на несколько таблиц, согласно категориям и переписывать в них только те записи, которые используются чисто для поиска, в 6 -7 раз точно получу прирост в скорости
+ выборку данных можно сделать без группировок, а сортировать уже средствами скрипта ...
 

Krishna

Продался Java
Black Rabbit

1. Какая СУБД, почему до сих пор не указал(а)(о)?

2. Покажи результаты вот этих четырех запросов (СТРОГО в том виде, что я написал, без своих правок):

select COUNT(*) from options_filled where (oid='26' and value='0');

select COUNT(*) from options_filled where (oid='29' and value>='10');

select COUNT(*) from options_filled where (oid='33' and value='0');

select COUNT(*) from options_filled WHERE 1=1;

-~{}~ 10.12.06 15:27:

а сортировать уже средствами скрипта ...
маразм.
И вообще, вопрос уже больно вырос. По-крайней мере, нужна схема бд.
 
Сверху