2014-02-18 8 views
0

У меня есть следующий MySQL QueryКак я могу улучшить производительность этого MySQL INNER JOIN?

SELECT p. * 
FROM posts AS p 
INNER JOIN followings AS f ON p.id_user = f.id_user 
WHERE 
f.id_me =(my id) 
ORDER BY id LIMIT 11 

У меня есть индексы для:

  • id_user в posts таблице
  • id_user, id_me в followings таблице.

100K строк в таблице followings, 30K строк в таблице posts.

У меня вопрос, требуется больше 1 секунды, можно ли написать этот запрос, который занимает несколько миллисекунд?

+0

Запустите 'EXPLAIN' и опубликуйте его. –

+1

правило большого пальца: любое поле, используемое в 'join' или' where', а иногда и 'order by' должно иметь индекс на нем. но кроме этого, в вашем запросе очень мало, что можно оптимизировать на уровне запросов - либо добавлять индексы по мере необходимости, либо получать более быстрый сервер БД. –

+0

, который является порядком по идентификатору «ID». Вы должны привыкнуть к запросам с помощью table.column ... или alias.column, поскольку другие пытаются помочь определить правильный контекст происхождения таблицы. – DRapp

ответ

0
SELECT p. * 
FROM posts AS p 
INNER JOIN (SELECT id_me, id_user from followings order by id_me, id_user) AS f ON p.id_user = f.id_user 
WHERE 
f.id_me =(my id) 
ORDER BY id LIMIT 11 

Создав sub_query, вы помещаете индекс в идентификаторы без изменения таблицы. Это должно ускорить время. Если это не работает, и он использует ненадлежащей индекс для данного запроса, вы можете использовать force_index ... но это должно помочь немного ...

+0

как бы это было быстрее? Теперь вы запускаете два запроса вместо одного. –

+0

, потому что он ограничивает столбцы, которые он вытаскивает со второй таблицы, а также таблицу, в которой он не вытаскивает какую-либо информацию из выбора ... – Hituptony

+0

находится в соединении – Hituptony

0

Попробуйте это:

select p. * 
    from posts p 
    where p.id_user in 
    (select f.id_user 
     from 
    followings f 
    where 
    f.id_me =(my id)) 
    order by id limit 11 

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

-2

Если добавление индексов является опцией, добавьте один для id (в зависимости от того, из какой таблицы), поскольку он используется для ORDER. См. http://www.mysqlperformanceblog.com/2006/09/01/order-by-limit-performance-optimization/ У меня возникли проблемы с большими таблицами с 30 секунд до 3 секунд, добавив индекс в пункт ORDER.

Также рекомендуется, чтобы столбец ORDER происходил от ведущего стола. Поэтому, если id из таблицы posts, то это уже верно, но если нет, отмените таблицы в запросе, выбрав FROM followings и JOIN posts.

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

+0

Это не поможет, так как это не поможет MySql быстро добраться до данных. Объем данных, которые необходимо отсортировать, будет незначительным по сравнению с объемом данных, которые необходимо просеять, чтобы найти нужные данные для сортировки. –

0

В вашем запросе нет ничего принципиально неправильного, и ваши индексы не за горами.

Для того, чтобы получить максимальную отдачу от индексов, важно понять не только , которые столбцов будут использоваться, но наиболее эффективный порядок, в котором они должны быть использованы для того, чтобы получить данные из.

Замените свой индекс на following на номер id_me, id_user (в обратном порядке).

Таким образом MySql может:

  • Найти правильные строки в following первой, глядя в небольшой кусочек указательным (как лучший способ уменьшить объем работы он должен сделать)
  • Используйте данные id_user в индексе на following для того, чтобы ...
  • Найдите правильные строки в posts, используя существующий индекс на этой таблице.

В основном пытаются выяснить, как вы бы найти данные, а затем предоставить индексы, чтобы помочь MySql сделать это для вас.

+0

Разве я не делал этого в подзапросе? – Hituptony

+0

Да, вы просите MySql сделать это, я помогу вам создать индексы, которые означают, что MySql может сделать это своевременно (согласно вашему вопросу). И.Е. В вашем запросе нет ничего принципиально неправильного. –

+0

Спасибо, Роб. Хорошее объяснение – Hituptony

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