SQLinfo.ru - Все о MySQL

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

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

Вы не зашли.

#1 09.02.2009 18:36:27

sincous
Участник
Зарегистрирован: 09.02.2009
Сообщений: 1

Простейший поисковый механизм. Помогите с оптимизацией.

Использую три таблицы.
index_id, index_pages, index_words.
В index_words хранятся собственно ключевые слова. В index_id связи между ключевым словом (index_words.id = index_id.wid) и страницей, где это ключевое слово присутствует (index_pages.id = index_id.pid).
На сайте уже 726 страниц, 64,713 ключевых слов, 339,963 связей.
Запросы на выборку:

SELECT DISTINCT url, title, content
FROM index_pages ip, index_words iw, index_id inid
WHERE iw.word LIKE "%слово%"
AND iw.id = inid.wid
AND inid.pid = ip.id
ORDER BY time DESC

(для одного слова)

SELECT DISTINCT url, title, content
FROM `index_pages`
INNER JOIN `index_id` ON `index_pages`.`id` = `index_id`.`pid`
INNER JOIN `index_words` ON `index_words`.`id` = `index_id`.`wid`
WHERE `index_words`.`word` LIKE "%слово1%"
OR `index_words`.`word` LIKE "%слово2%"
GROUP BY `index_pages`.`id`
HAVING COUNT( `index_words`.`id` ) >=2
ORDER BY index_pages.time DESC

(для двух слов, и по такому же принципу для 3 слов)

Подскажите, почему выборка тормозит (запрос выполняется уже более 1-2 секунд, и сайт стремительно развивается...), возможно есть другие реализации архитектуры для поисковика?
Таблицы:
CREATE TABLE `index_id` (
              `wid` int(10) unsigned NOT NULL,
              `pid` int(11) NOT NULL,
                  PRIMARY KEY  (`wid`,`pid`)
        ) ENGINE=MyISAM;
CREATE TABLE `index_pages` (
              `id` int(11) NOT NULL auto_increment,
              `url` tinytext,
              `title` tinytext,
              `content` text,
              `time` datetime NOT NULL default "0000-00-00 00:00:00",
                  PRIMARY KEY  (`id`)
        ) ENGINE=MyISAM;
CREATE TABLE `index_words` (
              `id` int(10) unsigned NOT NULL auto_increment,
              `word` varchar(250) NOT NULL,
                  PRIMARY KEY  (`id`),
                      KEY `id` (`id`),
                      KEY `name` (`word`)
        ) ENGINE=MyISAM;

Explain:

(поиск с одним словом)
id     select_type     table     type     possible_keys     key     key_len     ref     rows     Extra
1    SIMPLE    inid    index    PRIMARY    PRIMARY    8    NULL    339963    Using index; Using temporary; Using filesort
1    SIMPLE    iw    eq_ref    PRIMARY    PRIMARY    4    test.inid.wid    1    Using where
1    SIMPLE    ip    eq_ref    PRIMARY    PRIMARY    4    test.inid.pid    1    
(поиск с двумя словами)
id     select_type     table     type     possible_keys     key     key_len     ref     rows     Extra
1    SIMPLE    index_id    index    PRIMARY    PRIMARY    8    NULL    339963    Using index; Using temporary; Using filesort
1    SIMPLE    index_words    eq_ref    PRIMARY    PRIMARY    4    test.index_id.wid    1    Using where
1    SIMPLE    index_pages    eq_ref    PRIMARY    PRIMARY    4    test.index_id.pid    1    
(поиск по трём словам)
id     select_type     table     type     possible_keys     key     key_len     ref     rows     Extra
1    SIMPLE    index_id    index    PRIMARY    PRIMARY    8    NULL    339963    Using index; Using temporary; Using filesort
1    SIMPLE    index_words    eq_ref    PRIMARY    PRIMARY    4    test.index_id.wid    1    Using where
1    SIMPLE    index_pages    eq_ref    PRIMARY    PRIMARY    4    test.index_id.pid    1

Отредактированно sincous (09.02.2009 18:37:50)

Неактивен

 

#2 10.02.2009 16:21:08

Magz
Гуру
Откуда: Москва
Зарегистрирован: 18.09.2007
Сообщений: 112

Re: Простейший поисковый механизм. Помогите с оптимизацией.

1. У Вас неправильно построен ключ для поля id в таблице index_words - нельзя добавить primary и index одновременно на один столбец, поэтому сейчас индекс не используется в выборке.
2. У Вас идет сортировка по полю time, значит нужно построить индекс для этого поля.
3. Если я правильно понимаю, при конструкции "`word` LIKE "%слово%" индекс на varchar использоваться не будет. Для индекса нужно строгое равенство или LIKE "слово" для использования типа range.
4. Вам точно поле word нужно такое длинное? Чем меньше длинна, тем меньше длинна ключа, тем быстрее должен быть поиск.

Это на первый взгляд

P.S. После экспериментов, самым "тормозным" местом у меня стал именно WHERE iw.word LIKE "%слово%" Замена на iw.word = "слово" не спасает, все равно идет Using temporary; Using filesort. Получается, что стратегией оптимизации должно стать избавление от текстового поиска.

Отредактированно Magz (10.02.2009 17:19:20)

Неактивен

 

#3 10.02.2009 20:27:47

paulus
Администратор
MySQL Authorized Developer and DBA
Зарегистрирован: 22.01.2007
Сообщений: 6757

Re: Простейший поисковый механизм. Помогите с оптимизацией.

Раз уж у Вас таблички MyISAM - грех не воспользоваться полнотекстовым индексом?
http://dev.mysql.com/doc/refman/5.1/en/ … guage.html

В сообщении Magz в первом пункте следует читать "смысла в обычном индексе при этом нет" smile

Неактивен

 

Board footer

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