Форум: Форум PHPФорум ApacheФорум Регулярные ВыраженияФорум MySQLHTML+CSS+JavaScriptФорум FlashРазное
Новые темы: 0000000
Социальная инженерия и социальные хакеры. Авторы: Кузнецов М.В., Симдянов И.В. Самоучитель PHP 5 / 6 (3 издание). Авторы: Кузнецов М.В., Симдянов И.В. PHP 5. На примерах. Авторы: Кузнецов М.В., Симдянов И.В., Голышев С.В. PHP. Практика создания Web-сайтов (второе издание). Авторы: Кузнецов М.В., Симдянов И.В. MySQL 5. В подлиннике. Авторы: Кузнецов М.В., Симдянов И.В.
ВСЕ НАШИ КНИГИ
Консультационный центр SoftTime

Форум MySQL

Выбрать другой форум

 

Здравствуйте, Посетитель!

вид форума:
Линейный форум Структурный форум

тема: как оптимизировать многотабличный запрос (+ вложенный запрос в WHERE-конструкции)?
 
 автор: Zilog   (14.04.2011 в 03:07)   письмо автору
 
 

хочу сделать новости.

Дано:
1. Новостей много — 2,5 тыс. штук.
2. Новость может быть на разных языках
3. Новость может относится к одной или нескольким категориям

Таб.1 (news) - собственно новость с датой
news_id, date

Таб.2 (data) - содержание новости
data_id, news_id, lang_id, caption, text

Таб.3 (news2cat) - категории новости
id, news_id, cat_id

Таб.3 (cat) - категории (спорт, политика и т.п.)
cat_id, cat_caption


Всё заработало, НО! очень тормозит выборка, секунд по пять думает.
Делаю так.

  SELECT n.*, d.*
  FROM news AS n
  LEFT JOIN data AS d ON (d.news_id = n.news_id)
  WHERE  n.news_id IN (SELECT news_id FROM  news2cat WHERE cat_id = 2)
  AND d.lang_id = "ru" AND n.date > 123123123 AND n.date < 123123123
  ORDER BY n.date DESC


123123123 (для примера) - это timestamp.

Как бы сдлеать такую выборку быстрее? Насколько мне удалось понять, тормозит проверка на принадлежность к нужной категории:

WHERE  n.news_id IN (SELECT news_id FROM  news2cat WHERE cat_id = 2)


чем бы это заменить?

  Ответить  
 
 автор: cheops   (14.04.2011 в 09:11)   письмо автору
 
   для: Zilog   (14.04.2011 в 03:07)
 

1. Самый быстрый способ, это проиндексировать таблицы. Таблицы индексированы, если да, то расскажите подробнее как они индексированы?
2. Второй способ избавиться от вложенного запроса и добавить его в качестве третей таблицы в FROM (если у вас таблицы индексированы, индексы будут использоваться более эффективно, чем во вложенных запросах).

  Ответить  
 
 автор: Zilog   (14.04.2011 в 11:14)   письмо автору
 
   для: cheops   (14.04.2011 в 09:11)
 

не совсем понял что значит "проиндексированы ли таблицы" — у меня во всех таблицах первм полем идёт первичный ключ, с автоинкрементом, он же используется для связи таблиц между собой. Это имеется ввиду?

пробовал ещё два варианта (выполнилось за 0.35-0.37):

  SELECT nc.*, n.*, d.* 
  FROM news2cat AS nc 
  LEFT JOIN news AS d ON (n.news_id = nc.news_id) 
  LEFT JOIN data AS d ON (d.news_id = nc.news_id) 
  WHERE nc.cat_id = 2  AND d.lang_id = "ru" 
  AND n.date > 123123123 AND n.date < 123123123 
  ORDER BY n.date DESC 


и (выполнилось так же за 0.35-0.37):

  SELECT nc.*, n.*, d.* 
  FROM news2cat AS nc, news AS n, data AS d
  WHERE   nc.cat_id = 2 
  AND d.lang_id = "ru" 
  AND n.news_id = nc.news_id 
  AND d.news_id = nc.news_id 
  AND n.date > 123123123 
  AND n.date < 123123123 
  ORDER BY n.date DESC 


Результат заметно лучше, вместо прежних 5 секунд.
Но всё равно как то не быстро, солглашаться на такие потери — так скоро сайт минуту открываться будет.
Ещё при том, что кол-во записей в таблице, предположительно, будет расти.

  Ответить  
 
 автор: cheops   (14.04.2011 в 11:35)   письмо автору
 
   для: Zilog   (14.04.2011 в 11:14)
 

Выполните запрос SHOW CREATE TABLE news2cat и поместите результаты сюда. Помимо первичных ключей в таблицу можно ввести дополнительные ключи, которые ускорят запросы на выборку. Например nc.cat_id и n.date можно проиндексировать и посмотреть не ускорит ли это запрос.

>0.35-0.37
>вместо прежних 5 секунд.
Это на сервере или на локальной машине?

  Ответить  
 
 автор: Zilog   (28.04.2011 в 15:03)   письмо автору
 
   для: cheops   (14.04.2011 в 11:35)
 

>Помимо первичных ключей в таблицу можно ввести дополнительные ключи, которые ускорят запросы на выборку. Например nc.cat_id и n.date можно проиндексировать и посмотреть не ускорит ли это запрос.

Ввёл, ускорилось.

>>0.35-0.37
>>вместо прежних 5 секунд.
>Это на сервере или на локальной машине?

На сервере, но это уже в прошлом - с индексами работает бысто. Спасибо, не знал про них.

Вопросы возникли:

Почитал:
http://www.softtime.ru/forum/read.php?id_forum=3&id_theme=14171

возник вопрос как теперь делать структуры таблиц.
Обязательно нужен ли primary? Или можно обойтись только индексом?

В моём случае, я сделал след. изменения:

Таб.1
news_id — изменил примари на индекс.

Таб.2 (data)
на news_id установил индекс

Таб.3 (news2cat)
на news_id и cat_id - установил индекс

т.е. сделал индексами те поля, через которые устанавливается связи между записями. Волнует только судьба news_id в первой таблице, то, что поле теперь не примари. Волнения обоснованы?

  Ответить  
 
 автор: cheops   (28.04.2011 в 15:31)   письмо автору
 
   для: Zilog   (28.04.2011 в 15:03)
 

>Волнения обоснованы?
Если это вам не мешает - пользуйтесь на здоровье. Таблица не обязана иметь первичный ключ или индексируемый столбец. Отсутствие первичного ключа - это обычное явление в мире СУБД, особенно в больших базах данных, где неиспользуемый первичный ключ может стать довеском к объему таблицы, замедляющим её обработку.

  Ответить  
 
 автор: Zilog   (28.04.2011 в 16:45)   письмо автору
 
   для: cheops   (28.04.2011 в 15:31)
 

>Если это вам не мешает - пользуйтесь на здоровье.

Спасибо, друг.

Trianon тут писал:

И еще, по-моему, обычно ключ подразумевает уникальность записи, т.е. возможность
 по ключу получить строго одну запись, ну или ни одной , если совсем не повезло. Индекс, 
это лишь механизм 
 ускорения поиска, индексироваться могут и такие поля, которые 
однозначно запись не идентифицируют, и  могут дать несколько записей с одним и тем 
же значением индексируемого поля (или совокупности полей) .


Взволновавшие моменты выделил. Боюсь вот чего — не всплывут ли косыки при выборке, не нарушатся ли связи между записями? Понимаю, вопрос может быть глупым, однако, я не спец за сим и спрашиваю.

  Ответить  
 
 автор: cheops   (28.04.2011 в 16:48)   письмо автору
 
   для: Zilog   (28.04.2011 в 16:45)
 

Нет, если вы используете надежный механизм назначения уникального значения, вроде AUTO_INCREMENT, таких ситуаций не возникнет, а связи не нарушатся (ну если не прикладывать специальных усилий для их разрушения :).

  Ответить  
 
 автор: Zilog   (28.04.2011 в 16:52)   письмо автору
 
   для: cheops   (28.04.2011 в 16:48)
 

>Нет, если вы используете надежный механизм назначения уникального значения, вроде AUTO_INCREMENT, таких ситуаций не возникнет, а связи не нарушатся (ну если не прикладывать специальных усилий для их разрушения :).

Спасибо, камрад!

  Ответить  
Rambler's Top100
вверх

Rambler's Top100 Яндекс.Метрика Яндекс цитирования