Задавайте вопросы, мы ответим
Вы не зашли.
Страниц: 1
Пример,
Select *From films f, zanr_film zf where flag_film=1 and zf.id_film=f.id_film and id_zanr=15 order by name_film
Выполняется за 0.3 сек.
Select *From films f, zanr_film zf where flag_film=1 and zf.id_film=f.id_film and id_zanr=5 order by name_film
выполняется за 0.06 сек.
Разница в запросах id_zanr
В первом случае записей примерно 300 штук, во втором более 3.000
При этом, чем меньше записей в результате поиска, тем дольше работает запрос.
Отредактированно humbert (04.05.2010 15:09:25)
Неактивен
А EXPLAIN от запросов покажите, пожалуйста?
Ну и надо понимать, что при таких скоростях ответа могут влиять разнообразные
факторы (загруженность машинки, загружена ли табличка в память, query cache,
еще какие-то).
Неактивен
Первый запрос, где меньше записей (id_zanr=15)
id select_type table type possible_keys key key_len ref rows Extra
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE f ref PRIMARY,name_film_2,view_film,date_public,duration... name_film_2 4 const 16569 Using where
1 SIMPLE zf eq_ref id_zanr_2 id_zanr_2 8 zxkino.f.id_film,const 1 Using index
Второй запрос, где записей больше (id_zanr=5)
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE f ref PRIMARY,name_film_2,view_film,date_public,duration... name_film_2 4 const 16569 Using where
1 SIMPLE zf eq_ref id_zanr_2 id_zanr_2 8 zxkino.f.id_film,const 1 Using index
CREATE TABLE zanr_film (
id_zanr int(11) NOT NULL,
id_film int(11) NOT NULL,
UNIQUE KEY id_zanr_2 (id_film,id_zanr)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
Если убрать KEY id_zanr_2, то запрос, где записей меньше выполняется быстрее, а там, где их больше, медленее
Отредактированно humbert (04.05.2010 15:48:55)
Неактивен
У Вас ключ неудачный — приходится бежать по всей табличке и выискивать значения.
Попробуйте сделать ключики (id_zanr) на табличке zanr_film и ключик (id_film, name_film)
на films.
Ну и если у Вас есть уникальный ключ над not-null полями, то стоит, наверное, его
назвать primary key
Неактивен
Спасибо за помощь, но ситуация такая же. Играл с индексами, разные ставил. Либо быстро выбираются те, которых меньше, либо наоборот. Но вот чтобы оба варианта работало не получилось.
Неактивен
Без explain все равно ничего сделать не удастся
Неактивен
Да explain показывает одно и тоже на обоих запросах.
Неактивен
Приходит человек к врачу:
— Доктор, у меня сын и дочка — у обоих красные пятна по лицу пошли!
— Покажите их.
— Они дома остались, я не решился их с собой взять.
— Ну, тогда я ничего сказать не могу.
— Но у них же у обоих одинаковые красные пятна по лицу!
Да, у Вас две одинаково плохие выборки. И я с ними ничего сделать не могу,
пока не увижу симптомы. Даже если они одинаковые
Неактивен
Спасибо за помощь и за потраченное время.
Если у Вас есть еще время и желание помочь (понять), то вот сами таблицы
CREATE TABLE films (
id_film int(11) NOT NULL auto_increment,
name_film varchar(255) NOT NULL,
eng_film varchar(255) NOT NULL,
duration_film int(11) NOT NULL,
opis_film text,
reiting_imdb float NOT NULL,
year_film int(4) NOT NULL,
trailer_url varchar(255) NOT NULL,
slug_film varchar(255) NOT NULL,
code_char_film int(11) default NULL,
description_film text,
door_title varchar(255) NOT NULL,
door_keyword varchar(255) NOT NULL,
door_description text,
door_opis text,
view_film int(11) NOT NULL,
title_film varchar(255) NOT NULL,
main_img varchar(255) NOT NULL,
trailer_width int(11) NOT NULL,
trailer_height int(11) NOT NULL,
date_public int(11) NOT NULL,
reiting_kinopoisk float NOT NULL,
reiting_site float NOT NULL,
keyword_film varchar(255) NOT NULL,
peremen_film text NOT NULL,
flag_film int(1) NOT NULL,
PRIMARY KEY (id_film),
UNIQUE KEY slug_film (slug_film,code_char_film),
KEY name_film (name_film)
) ENGINE=MyISAM AUTO_INCREMENT=16574 DEFAULT CHARSET=utf8;
CREATE TABLE zanr_film (
id_zanr int(11) NOT NULL,
id_film int(11) NOT NULL,
PRIMARY KEY (id_film,id_zanr)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
В films более 16.000 записей, в zanr_film более 25000, при этом id_zanr не более 25 штук всего. У некоторых фильмов несколько жанров. Из 25 жанров есть такие, у которых всего 24 фильма, а есть такие, у которых более 4.000 фильмов.
Нужно вывести список фильмов определенных жанров, и вот тут то и есть тормоза. Если стоит index в zanr_film по id_film, то быстрее всего выводится список для жанра, который имеет наибольшее количество фильмов. Если индекс отсутствует, то жанр с наименьшим количеством будет быстрее обрабатываться.
Неактивен
Ахаа, вот и начинает проясняться
Проблема такая: Вы пытаетесь выбрать бОльшую часть таблицы. Это практически
всегда приводит к тому, что таблица сканируется целиком на предмет нужных
строк, полностью игнорируя любые индексы. Если бы Вы туда ввели разумный
LIMIT (который Вам в любом случае нужен), то ситуация была бы совсем другой
Ситуация «маленькая выборка»: индекс на zanr_film(id_zanr) позволит выбрать id
фильмов, а потом выбрать из основной таблицы соответствующее небольшое
количество строк.
Ситуация «большая ограниченная выборка»: индекс на film (flag_film, name_film)
позволит выбирать данные в нужном порядке, учитывая наличие флага. Каждую
выбранную таким образом строчку нужно будет сверять с нужным жанром, но в
случае с LIMIT — это будет более простая операция.
Неактивен
Не совсем врубаюсь, можно языком для даунов?
Мне 2 запроса делать к БД: сначала id_film из таблицы жанров, а потом конкретные фильмы?
Неактивен
Добавьте индекс
ALTER TABLE zanr_film ADD INDEX (id_zanr) — это увеличит скорость работы в случае,
если выбирается небольшое количество строк.
Добавьте LIMIT 10 в конце запроса, чтобы работало всегда быстро
Неактивен
Вот так?
Select *From films f, zanr_film zf where flag_film=1 and zf.id_film=f.id_film and id_zanr=5 order by name_film Limit 10
Если так, то выполняется 0.5 сек.
Да и Limit 10 мне не особо нужен, т.к. осуществляю постраничный вывод фильмов, т.е. используется и Limit 10000, 90
А с индексами пробовал по разному, нашел закономерность, если много фильмов в жанре, то ставим индекс на id_film
Alter Table zanr_film enable keys
,
если мало, то индекс убираем.
Alter Table zanr_film disable keys
Индекс стоит на id_film в zanr_film. Работает быстро.
Но опять уперся в Limit, если "Limit 0,90", то быстро (0.06 сек.) , если же "Limit 4734, 90", то примерно 1 сек. запрос выполняется.
Еще раз спасибо за помощь, за 10 лет, что работаю типа программистом, первый раз взялся изучать оптимизацию mysql
Неактивен
Ну, если Вы выбираете 10к строк, то половина секунды — неплохой результат
Добавить-убрать индекс — это операция, которую перед запросом делать не надо,
надо добавить его — и он будет работать для коротких запросов.
LIMIT 10000, 90 — это очень очень очень плохой запрос. Я говорил «очень»? К
счастью, люди не смотрят больше 3-4 страниц обычно (и, если Вы хотите их зас-
тавить это делать, то лучше подумайте, не сделать ли более глубокий рубрикатор).
Неактивен
Спасибо, будем думать дальше, как оптимизировать работу. Возможно будет лучшим предусмотреть кеширование данных в файл и выдавать кеш. Правда тут возникает проблема актуальности данных, но что-нить придумаю.
Спасибо за помощь
Неактивен
Ну, можете настроить Query Cache — тогда он будет инвалидироваться автоматом.
Для популярных одиночных запросов — очень даже полезная штука.
Неактивен
Спасибо еще раз. Низко кланяюсь.
Неактивен
Страниц: 1