Задавайте вопросы, мы ответим
Вы не зашли.
Страниц: 1
Здравствуйте! Прошу помочь с оптимизацией запроса, который используется для административных целей на сайте (просмотр объектов начиная с новых)
Имеется 2 таблицы my_objects и my_object_history, в первой ~56 тыс. записей, во второй - 95тыс. записей, рост ожидается.
Запрос:
SELECT `id`, `url`, `last_update`, `got`, `yan`, `ipo` FROM (`my_objects`) JOIN `my_object_history` ON `my_object_history`.`id_object` = `my_objects`.`id` WHERE `dateend` = 2146132800 ORDER BY `id` desc LIMIT 10
Раньше выполнялся доли секунд, но при стремительном росте записей теперь не менее 9 сек.
Результат выполнения explain:
INSERT INTO `unknown` (`id`, `select_type`, `table`, `type`, `possible_keys`, `key`, `key_len`, `ref`, `rows`, `Extra`) VALUES ('1', 'SIMPLE', 'my_object_history', 'ref', 'PRIMARY,i_dateend', 'i_dateend', '4', 'const', '61169', 'Using temporary; Using filesort'); INSERT INTO `unknown` (`id`, `select_type`, `table`, `type`, `possible_keys`, `key`, `key_len`, `ref`, `rows`, `Extra`) VALUES ('1', 'SIMPLE', 'my_objects', 'ref', 'PRIMARY', 'PRIMARY', '4', 'bname.my_object_history.id_object', '1', '');
Индексы на полях:
my_objects - (id,url), last_update
my_object_history - (id_object, datebegin), dateend
Отредактированно futurama (08.12.2009 18:31:27)
Неактивен
Сейчас попытался добавить по одному доп. индексу в дополнение к составным индексам на обоих таблицах, ничего не изменилось, удалил эти индексы (данный запрос занял ~10 сек. на каждый запрос удаления), и вышеописанный запрос по выборке сортированных данных отработал снова за доли секунд. Через постраничную навигацию (в запросе Offset XXXX) просмотрел другие списки объектов, также быстро отработано, но если просматривать записи начиная с самых старых - все равно все слишком долго. Это уже что-то, тем более, что мне нужно в общем случае только свежие записи просматривать, но мне не понятно, что происходит. Может, я удалением одиночных индексов заставил MySQL пересоздать составные индексы?
Неактивен
Боюсь, оптимизировать надо данные. Скорее всего, нужна денормализация.
Возможно, будет неплохо работать
SELECT STRAIGHT_JOIN ...
FROM my_objects FORCE INDEX (PRIMARY)
JOIN my_object_history ON ...
WHERE `dateend` = 2146132800
ORDER BY `id` desc
LIMIT 10
Но он тоже будет сильно деградировать при росте количества строк с одинаковой
датой окончания.
Неактивен
Приведенный Вами запрос отрабатывает также по времени, как и мой, к сожалению, ничего не изменилось.
По поводу оптимизации данных: БД разрабатывалась с учетом данной работы - http://rdbms.narod.ru/article/history/index.html , используется одна таблица для всех записей истории данных. Также посматривал в статью http://rsdn.ru/article/db/dbhistory.xml, но решил выбрать первую в качестве основы. Видимо, промахнулся.
В таком случае, может быть, подскажете шаблоны проектирования, которые лучше подойдут для создания таблиц с историей данных каждого объекта? У меня в таблице объектов хранятся сами объекты и информация о них. В таблице истории хранятся записи истории данных объектов (по одной записи для каждого изменения данных), а для последней (свежей) версии данных объекта поле `dateend` = 2146132800. По производительности пока беспокоит только вышеописанный запрос, остальным не требуется выводить списки объектов вместе с данными, а вывод из БД одного объекта с данными (текущими и всех) не занимает значительного времени.
Неактивен
Ну, тогда только денормализация. Или порядок сортировки выбрать по какому-то
полю из истории
Неактивен
Ясно. спасибо и на этом
Кстати, после игры с индексами на удаленном сервере (проверил - все осталось как было прежде) оператор explain стал выдавать разные результаты на локальной машине и на удаленном сервере:
На локалке:
INSERT INTO `unknown` (`id`, `select_type`, `table`, `type`, `possible_keys`, `key`, `key_len`, `ref`, `rows`, `Extra`) VALUES ('1', 'SIMPLE', 'cp_object_history', 'ref', 'PRIMARY,i_dateend', 'i_dateend', '34', 'const', '154', 'Using temporary; Using filesort'); INSERT INTO `unknown` (`id`, `select_type`, `table`, `type`, `possible_keys`, `key`, `key_len`, `ref`, `rows`, `Extra`) VALUES ('1', 'SIMPLE', 'cp_objects', 'ref', 'PRIMARY', 'PRIMARY', '34', 'bname_new.cp_object_history.id_object', '1', '');
На сервере:
INSERT INTO `unknown` (`id`, `select_type`, `table`, `type`, `possible_keys`, `key`, `key_len`, `ref`, `rows`, `Extra`) VALUES ('1', 'SIMPLE', 'cp_objects', 'index', 'PRIMARY', 'PRIMARY', '771', NULL, '55638', ''); INSERT INTO `unknown` (`id`, `select_type`, `table`, `type`, `possible_keys`, `key`, `key_len`, `ref`, `rows`, `Extra`) VALUES ('1', 'SIMPLE', 'cp_object_history', 'ref', 'PRIMARY,i_dateend', 'PRIMARY', '4', 'bname.cp_objects.id', '950', 'Using where');
И хотя скорость при выборке самых старых записей стала ~5 cек, свежие выводятся достаточно быстро. С чем связаны подобные изменения, не знаю, в mysql не глубоко разбирался, и как видится, зря.
Неактивен
Вы бы еще писали explain в человекочитаемом виде, а не в виде INSERTов
Рад, что разобрались.
Неактивен
Извините, честно говоря, не знал, как лучше их вставить. Спасибо)
Неактивен
Страниц: 1