2015-03-29 3 views
1

Я не эксперт в области SQL, у меня есть SQL заявление:SQL: Как уменьшить время выполнения инструкции?

SELECT * FROM articles WHERE article_id IN 
(SELECT distinct(content_id) FROM contents_by_cats WHERE cat_id='$cat') 
AND permission='true' AND date <= '$now_date_time' ORDER BY date DESC; 

Таблица contents_by_cats имеет 11000 строк.

Таблица articles имеет 2700 строк.

Переменные $now_date_time и $cat являются переменными php.

Этот запрос занимает около 10 секунд, чтобы вернуть значения (я думаю, потому что он имеет вложенные операторы SELECT), а 10 секунд - большое количество времени.

Как я могу достичь этого по-другому? (Виды или ВСТУПЛЕНИЕ)?

Я думаю, что JOIN поможет мне здесь, но я не знаю, как правильно использовать его для оператора SQL, о котором я упоминал.

Заранее спасибо.

ответ

1

A JOIN - это именно то, что вы ищете. Попробуйте что-то вроде этого:

SELECT DISTINCT articles.* 
FROM articles 
JOIN contents_by_cats ON articles.article_id = contents_by_cats.content_id 
WHERE contents_by_cats.cat_id='$cat' 
AND articles.permission='true' 
AND articles.date <= '$now_date_time' 
ORDER BY date DESC; 

Если запрос еще не так быстро, как хотелось бы, то убедитесь, что у вас есть индекс по articles.article_id и contents_by_cats.content_id и contents_by_cats.cat_id. В зависимости от данных вам также может понадобиться индекс на articles.date.

Обратите внимание, что если значения $cat и $now_date_time исходят от пользователя, тогда вы действительно должны готовить и связывать запрос, а не просто сбрасывать эти значения в запрос.

+0

Да, я пробовал, потребовалось 12 секунд, что вы подразумеваете под индексом? –

+0

Хммм, увеличившись с 10 до 12 секунд, не подходит для вас? :-) –

+0

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

1

Это запрос, мы начинаем с:

SELECT a.* 
FROM articles a 
WHERE article_id IN (SELECT distinct(content_id) 
        FROM contents_by_cats 
        WHERE cat_id ='$cat' 
        ) AND 
     permission ='true' AND 
     date <= '$now_date_time' 
ORDER BY date DESC; 

Две вещи помогут этот запрос. Во-первых, переписать его с помощью exists, а не in и упростить подзапрос:

SELECT a.* 
FROM articles a 
WHERE EXISTS (SELECT 1 
       FROM contents_by_cats cbc 
       WHERE cbc.content_id = a.article_id and cat_id = '$cat' 
      ) AND 
     permission ='true' AND 
     date <= '$now_date_time' 
ORDER BY date DESC; 

Во-вторых, вы хотите индексы на обоих articles и contents_by_cats:

create index idx_articles_3 on articles(permission, date, article_id); 
create index idx_contents_by_cats_2 on contents_by_cat(content_id, cat_id); 

Кстати, вместо $now_date_time, вы можете просто использовать функцию now() в MySQL.

+0

Хорошо, и должен ли я назначить «Первичный ключ»? –

+0

@GordonLinoff, еще 20 лет назад (когда я занимался своим последним профессиональным развитием), он был недоволен использованием подзапросов. Почти в каждом случае мы обнаружили, что они ухудшают производительность. Теперь я вижу, как все делают это и находят реальные улучшения в производительности. Есть ли какие-либо статьи, которые помогут мне ускориться, когда использовать JOIN и когда использовать подзапросы? –

+0

@PeterBowers. , , Я могу сопереживать. Я узнал, что коррелированные подзапросы и «как» были плохими (между прочим), и им пришлось узнать, что оптимизаторы SQL со временем стали лучше. –

Смежные вопросы