оптимизация соединения mysql для больших запросов

#mysql

#mysql

Вопрос:

у меня такой большой запрос, и я не могу полностью перестроить приложение из-за клиента:

 SELECT count(AdvertLog.id) as count,AdvertLog.advert,AdvertLog.ut_fut_tstamp_dmy as day,
          AdvertLog.operation,
          Advert.allow_clicks,
          Advert.slogan as name, 
          AdvertLog.log,
                        (User.tx_reality_credit
             -20
            -(SELECT COUNT(advert_log.id) FROM advert_log WHERE ut_fut_tstamp_dmy <= day AND operation = 0 AND advert IN (168))
             (SELECT IF(ISNULL(SUM(log)),0,SUM(log)) FROM advert_log WHERE ut_fut_tstamp_dmy <= day AND operation IN (1, 2) AND advert = 40341 )) AS points 
FROM `advert_log` AS AdvertLog
LEFT JOIN `tx_reality_advert` Advert ON Advert.uid = AdvertLog.advert
LEFT JOIN `fe_users` AS User ON (User.uid = Advert.user or User.uid = AdvertLog.advert)
WHERE User.uid = 40341 and AdvertLog.id>0
GROUP BY AdvertLog.ut_fut_tstamp_dmy, AdvertLog.advert
ORDER BY AdvertLog.ut_fut_tstamp_dmy_12 DESC,AdvertLog.operation,count DESC,name
LIMIT 0, 15
  

Это занимает примерно 1,5 с, что слишком долго.

Индексы:

 User.uid
AdvertLog.advert
AdvertLog.operation
AdvertLog.advert
AdvertLog.ut_fut_tstamp_dmy
AdvertLog.id
Advert.user
AdvertLog.log
  

Вывод Explain:

 id  select_type table   type    possible_keys   key key_len ref rows    Extra
1       PRIMARY User    const    PRIMARY    PRIMARY 4       const 1     Using temporary; Using filesort
1       PRIMARY AdvertLog range  PRIMARY,advert PRIMARY 4   NULL 21427  Using where
1       PRIMARY Advert  eq_ref   PRIMARY    PRIMARY 4   etrend.AdvertLog.advert 1   Using where
3   DEPENDENT SUBQUERY  advert_log  ref ut_fut_tstamp_dmy,operation,advert  advert  5   const   1   Using where
2   DEPENDENT SUBQUERY  advert_log  index_merge ut_fut_tstamp_dmy,operation,advert  advert,operation    5,2 NULL    222 Using intersect(advert,operation); Using where
  

Кто-нибудь может мне помочь, потому что я пробовал разные вещи, но никаких улучшений

Комментарии:

1. Нет ли индекса Advert.uid ? (Кстати, реквизиты для предоставления ключевой / ПОЯСНЯЮЩЕЙ информации с места в карьер.)

Ответ №1:

Запрос довольно большой, и я ожидаю, что это займет немало времени, но вы можете попробовать добавить индекс в Advert.uid, если его нет. Кроме этого, кто-то с гораздо лучшим SQL-foo, чем я, должен будет ответить на этот вопрос.

Комментарии:

1. Да, в Advert.uid есть индекс

Ответ №2:

Во-первых, ваше предложение WHERE основано на конкретном «пользователе.ИДЕНТИФИКАТОР», но в Advert_Log есть индекс по объявлению (идентификатор пользователя). Итак, сначала измените предложение WHERE, чтобы отразить это…

 Where 
   AdverLog.Advert = 40341
  

Затем удалите «ЛЕВОЕ СОЕДИНЕНИЕ», чтобы просто «ПРИСОЕДИНИТЬСЯ» к пользовательской таблице.

Наконец (без полной перезаписи запроса), я бы выбрал ключевое слово «STRAIGHT_JOIN»…

 select STRAIGHT_JOIN
    ... rest of query ...
  

Который сообщает оптимизатору выполнить запрос в явно указанном порядке / отношениях.

Другой областью оптимизации было бы предварительное запрашивание «точек» (подсчетов и журналов на основе рекламы и операции) один раз и получение ответа из этого (в виде подзапроса) вместо того, чтобы выполнять два запроса)… но мне было бы интересно узнать влияние выше, ГДЕ помогает JOIN и STRAIGHT_JOIN.

Кроме того, просматривается соединение с пользовательской таблицей на основе ЛИБО Advert_Log.Advert (userId), либо TX_Reality_Credit .Пользователь (другой идентификатор пользователя, который, похоже, не совпадает, поскольку соединение между Advert_Log и TX_Reality_Credit (TRC) основано на TRC.UID), если это не неверное предположение. Это может привести к ошибочным результатам, поскольку вы тестируете НЕСКОЛЬКО идентификаторов пользователей … пользователя advert и того, кто еще является «пользователем» из таблицы «TRC»… что приведет к тому, какой кредит пользователя будет применен к вычислению «баллов».

Чтобы лучше понять взаимосвязь и контекст, не могли бы вы дать дополнительные разъяснения относительно того, что находится в этих таблицах с точки зрения Advert_Log до TX_Reality_Credit, и Advert vs UID vs User…

Комментарии:

1. Привет, спасибо за интересные предложения, я попробую их завтра утром на работе, чтобы объяснить, что пользователи путаются, кто-то, кто создал это приложение, разработал его довольно плохо, я не знаю, в чем причины, но объяснить:

2. в таблице объявлений есть рекламные объявления с пользовательским полем (владельцем рекламы) в качестве внешнего ключа, и в AdvertLog записываются клики по рекламе, а также когда пользователь покупает новый кредит. Щелчок — это цифры 1,2 в поле операции, а кредит на покупку равен 0. Вот в чем проблема, потому что, когда кто-то нажимает на рекламу, он записывает в AdvertLog.advert идентификатор рекламы, но если пользователь покупает кредит, он записывает в AdvertLog.advert идентификатор пользователя (владелец рекламы), вот почему присоединение пользователя к двум таблицам

3. @user1014954, что возвращает меня к содержанию моего вопроса… Какой пользователь должен использоваться для основы tx_reality_credit. Было бы хорошо, если бы вы предоставили некоторые примеры данных, показывающие некоторый контент из каждой таблицы (ИМЕНА ПРИМЕРОВ, где это применимо), чтобы мы могли лучше понять ваши отношения и ТО, с ЧЕМ будут работать элементы…

4. я добавлю некоторую информацию об этом завтра, сейчас у меня нет доступа к данным, и я написал это там неправильно. операция 0 — щелчок, а 1,2 — покупка кредита