|
|
|
| хочу сделать новости.
Дано:
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)
|
чем бы это заменить? | |
|
|
|
|
|
|
|
для: Zilog
(14.04.2011 в 03:07)
| | 1. Самый быстрый способ, это проиндексировать таблицы. Таблицы индексированы, если да, то расскажите подробнее как они индексированы?
2. Второй способ избавиться от вложенного запроса и добавить его в качестве третей таблицы в FROM (если у вас таблицы индексированы, индексы будут использоваться более эффективно, чем во вложенных запросах). | |
|
|
|
|
|
|
|
для: 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 секунд.
Но всё равно как то не быстро, солглашаться на такие потери — так скоро сайт минуту открываться будет.
Ещё при том, что кол-во записей в таблице, предположительно, будет расти. | |
|
|
|
|
|
|
|
для: Zilog
(14.04.2011 в 11:14)
| | Выполните запрос SHOW CREATE TABLE news2cat и поместите результаты сюда. Помимо первичных ключей в таблицу можно ввести дополнительные ключи, которые ускорят запросы на выборку. Например nc.cat_id и n.date можно проиндексировать и посмотреть не ускорит ли это запрос.
>0.35-0.37
>вместо прежних 5 секунд.
Это на сервере или на локальной машине? | |
|
|
|
|
|
|
|
для: 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 в первой таблице, то, что поле теперь не примари. Волнения обоснованы? | |
|
|
|
|
|
|
|
для: Zilog
(28.04.2011 в 15:03)
| | >Волнения обоснованы?
Если это вам не мешает - пользуйтесь на здоровье. Таблица не обязана иметь первичный ключ или индексируемый столбец. Отсутствие первичного ключа - это обычное явление в мире СУБД, особенно в больших базах данных, где неиспользуемый первичный ключ может стать довеском к объему таблицы, замедляющим её обработку. | |
|
|
|
|
|
|
|
для: cheops
(28.04.2011 в 15:31)
| | >Если это вам не мешает - пользуйтесь на здоровье.
Спасибо, друг.
Trianon тут писал:
И еще, по-моему, обычно ключ подразумевает уникальность записи, т.е. возможность
по ключу получить строго одну запись, ну или ни одной , если совсем не повезло. Индекс,
это лишь механизм ускорения поиска, индексироваться могут и такие поля, которые
однозначно запись не идентифицируют, и могут дать несколько записей с одним и тем
же значением индексируемого поля (или совокупности полей) .
|
Взволновавшие моменты выделил. Боюсь вот чего — не всплывут ли косыки при выборке, не нарушатся ли связи между записями? Понимаю, вопрос может быть глупым, однако, я не спец за сим и спрашиваю. | |
|
|
|
|
|
|
|
для: Zilog
(28.04.2011 в 16:45)
| | Нет, если вы используете надежный механизм назначения уникального значения, вроде AUTO_INCREMENT, таких ситуаций не возникнет, а связи не нарушатся (ну если не прикладывать специальных усилий для их разрушения :). | |
|
|
|
|
|
|
|
для: cheops
(28.04.2011 в 16:48)
| | >Нет, если вы используете надежный механизм назначения уникального значения, вроде AUTO_INCREMENT, таких ситуаций не возникнет, а связи не нарушатся (ну если не прикладывать специальных усилий для их разрушения :).
Спасибо, камрад! | |
|
|
|