Задавайте вопросы, мы ответим
Вы не зашли.
Страниц: 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)
Неактивен
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)
Неактивен
Раз уж у Вас таблички MyISAM - грех не воспользоваться полнотекстовым индексом?
http://dev.mysql.com/doc/refman/5.1/en/ … guage.html
В сообщении Magz в первом пункте следует читать "смысла в обычном индексе при этом нет"
Неактивен
Страниц: 1