![]() |
Показаны 9 сообщений на этой странице |
Форум сетевых администраторов (http://netadmin.ws/forum/index.php)
- MySQL (http://netadmin.ws/forum/forumdisplay.php?forumid=40)
-- Структура данных для индексатора - как? (http://netadmin.ws/forum/showthread.php?threadid=6889)
Структура данных для индексатора - как?
есть газета за 5 лет выложенная в нет в виде html файлов. объем всех файлов примерно 100-150 Mb надо их проиндексировать а затем осуществлять поиск по этой базе
по определенным соображениям я отказался от встроенного fulltex index (хотя может быть и напрасно)
я написал один скрипт который использовал БД с тремя таблицами
word(id_word,word)
article(id_article,article)
index(id_article,id_word,occurence)
принцип работы такой: вытаскивает из html файлавсе слова,берет по одному каждое слово проверяет если такое слово в таблице word если есть берет его id_word если нет записывает его туда с новым id_word,
в таблице article делаем запись о индексируемом файле и берем его id_article,
в таблице index ищем индексировали ли мы уже стсатью с такими id_article,id_word если да то увеличиваем occurence на 1 если нет то пишем новую запись
примерно так все и было
но потом я заметил что по мере того как я добавляю новые статьи скорость поиска резко снижается и уже по базе со статьями за 1 год
поиск производился за 17-19 секунд что по моему очень долго а
в таблице index больше 1.5 миллиона записей
Я решил переделать метод индексации таблицы word и article остались без изменения а вместо таблицы index сделал для каждой быквы алфавита свою таблицу типа a_index, b_index и т д
теперь за два 2 года поиск идет примерно за 2 секунды
но помоему это не эффективная структура получается через 5 лет поиск по архиву будет 5 секунд?
Кто знает как организовать правильное хранение индекса в базе данных какая должна быть структура базы?
например как хранятся данные в google.com?
кто что знает?
или перейти на встроенный fulltext index?
__________________
Сегодня я знаю больше чем вчера, завтра я буду знать больше чем сегодня
Ты когда обрабатывешь запрос поиска на "раз два три", то как в SQL пишешь ? А еще, как насчет полного синтаксиса таблиц ... со всеми ключами, типами ...
__________________
The time was broken ...
RaZEr
это таблицы
CREATE TABLE `a_occurrence` (
`word_id` int(10) unsigned NOT NULL default '0',
`page_id` int(10) unsigned NOT NULL default '0',
`count` int(10) unsigned NOT NULL default '0',
PRIMARY KEY (`word_id`,`page_id`),
KEY `page_id` (`page_id`)
) TYPE=MyISAM;
CREATE TABLE `main` (
`idtext` int(10) unsigned NOT NULL default '0',
`date` date NOT NULL default '0000-00-00',
`title` varchar(250) NOT NULL default '',
`donotindex` tinyint(10) unsigned NOT NULL default '0',
`words` mediumint(10) unsigned NOT NULL default '0',
`first_30` varchar(250) NOT NULL default '',
`issue` int(11) NOT NULL default '0',
`filename` varchar(100) NOT NULL default '0',
PRIMARY KEY (`idtext`),
UNIQUE KEY `filename` (`filename`),
KEY `issue` (`issue`),
KEY `title` (`title`(3))
) TYPE=MyISAM;
CREATE TABLE `word` (
`word_id` int(10) unsigned NOT NULL auto_increment,
`table_prefix` varchar(100) NOT NULL default '',
`word_word` varchar(50) NOT NULL default '',
PRIMARY KEY (`word_id`),
UNIQUE KEY `word_word` (`word_word`)
) TYPE=MyISAM;
в таблице main не обращай внимания на date, title, donotindex, words, first_30, issue
эти поля не используются в поиске а используются только как дополнительная информация
о статьях.
как работает индексатор.
1. берем html файл вытаскиваем все слова
2. делаем запись в таблице main для этой статьи
2. берем первое слово проверяем если оно в таблице word. если оно есть берем word_id и
table_prefix (это будет первая буква слова например - а).
если нет пишем новую запись.
3. делаем запись в соответствующей таблице
(если table_prefix = a то это будет a_occurrence)
main.idtext соответствует a_occurrence.page_id
если я ищу по Russian
SELECT main.idtext, main.title, main.donotindex, main.words, main.date,
count(DISTINCT main.idtext) AS dist_count, main.first_30
FROM main INNER JOIN r_occurrence ON r_occurrence.page_id = main.idtext
WHERE (( r_occurrence.word_id = '686' OR r_occurrence.word_id = '1818' ) )
GROUP BY main.idtext ORDER BY main.date DESC LIMIT 0,11
это значит что в таблице word есть например два слова Russian и Russians с word_id
686 и 1818 соответственно
если я ищу по Russian area
SELECT main.idtext, main.title, main.donotindex, main.words, main.date,
count(DISTINCT main.idtext) AS dist_count, main.first_30 FROM main
INNER JOIN a_occurrence ON a_occurrence.page_id = main.idtext
INNER JOIN r_occurrence ON r_occurrence.page_id = main.idtext
WHERE (( a_occurrence.word_id = '576' OR a_occurrence.word_id = '934' )
AND( r_occurrence.word_id = '686' OR r_occurrence.word_id = '1818' ) )
GROUP BY main.idtext ORDER BY main.date DESC LIMIT 0,11
тоже самое но уже для двух слов
если я ищу по Russian region
SELECT main.idtext, main.title, main.donotindex, main.words, main.date,
count(DISTINCT main.idtext) AS dist_count, main.first_30
FROM r_occurrence AS r_occurrence1, main
INNER JOIN r_occurrence ON r_occurrence.page_id = main.idtext
WHERE (( r_occurrence.word_id = '836' OR r_occurrence.word_id = '2182' OR r_occurrence.word_id = '2967' )
AND( r_occurrence1.word_id = '686' OR r_occurrence1.word_id = '1818' )
AND r_occurrence.page_id = r_occurrence1.page_id )
GROUP BY main.idtext ORDER BY main.date DESC LIMIT 0,11
если два слова начинаются на одну букву то значит они проиндексированны в одну таблицу
а значит мы не можем использовать SQL типа
SELECT page_id FROM r_occurrence WHERE word_id = 1 AND word_id = 2
приходиться делать ссылку на таблицу и SQL получается типа
SELECT page_id FROM r_occurrence, r_occurrence AS r_occurrence1
WHERE r_occurrence.word_id = 1 AND r_occurrence1.word_id = 2
как можно понять поиск происходит по логическому AND
в общем так все и работает.
__________________
Сегодня я знаю больше чем вчера, завтра я буду знать больше чем сегодня
На вскидку сложно говорить почему выбирает долго ... посмотри нужны ли тебе всякие ф-ии вроде DISTINCT ... потому что тормоза от них сплошные.
__________________
The time was broken ...
RaZEr
убрал DISTINCT поиск идет быстрее по некоторым запросам
быстрее до 10 раз а по некоторым столько же но это и понятно
зависит от размера таблицы на маленьких таблицах просто не
видно разницы
Спасибо!
Но меня волнует прежде всего вопрос правильная пи у меня
структура хранения индекса или правильнее было бы организовать
все по другому?
Какие еще могут быть варианты?
Где можно об этом почитать?
Не могу найти в сети ничего по этому вопросу
__________________
Сегодня я знаю больше чем вчера, завтра я буду знать больше чем сегодня
Narcom
а ресур =www.mnogosearch.ru случайно не поможет Вам...
nanut
был я там, только что от туда
одна из структур базы данных которую mnogosearch использует
для хранения индекса похожа на то что я сотворил.
Storage mode - multi по терминологии mnogoserch.
в storage mode - multi нет таблицы word как у меня
а в таблицах x_occurrence хранятся слова целиком
а не их id и наверное поиск идет сразу по слову
у меня же на данный момент происходит так
сначала в отдельном sql запрсое нахожу все id слов (word_id) и уже во втором sql запросе id статей (page_id) да наверное
если обходится только одним sql запрсом то быстрее будет.
но это только в теории потому что на сайте не возможно найти
описания работы движка mnogosearch, чем руководствовались
разработчики когда принимали те или иные решения и т д,
а копаться в исходниках нехватает знаний и времени.
mnogosearch и другие его сотоварищи из Search Software Projects
это круто это готовое решение когда ты можеш устанавливать
программы на сервере.
У меня же только PHP+MySQL
Narcom добавил 01-11-2003 в 15:16:36:
недавно нашел
кто юзал phpdig
PhpDig Website : http://phpdig.toiletoine.net/
немного старый скрипт но это примерно то что мне надо
кто индексировал на нем 100 - 150 Mb текста отзовись!
__________________
Сегодня я знаю больше чем вчера, завтра я буду знать больше чем сегодня
а Индексы расставлять не пробовал?
__________________
http://phpclub.net
Yuriy_S
что то не совсем понимаю Какие Индексы??
например в таблице
CREATE TABLE `a_occurrence` (
`word_id` int(10) unsigned NOT NULL default '0',
`page_id` int(10) unsigned NOT NULL default '0',
`count` int(10) unsigned NOT NULL default '0',
PRIMARY KEY (`word_id`,`page_id`),
KEY `page_id` (`page_id`)
) TYPE=MyISAM;
целых два индекса. Мне даже кажется что KEY `page_id` (`page_id`)
лишний индекс потомучто Explain показывает сто используется
только PRIMARY KEY (`word_id`,`page_id`)
объясни ты очем?
__________________
Сегодня я знаю больше чем вчера, завтра я буду знать больше чем сегодня
| Формат времени GMT. Текущее время 15:25. | Показаны 9 сообщений на этой странице |
Powered by: vBulletin Version 2.2.4
Copyright © Jelsoft Enterprises Limited 2000, 2001.