2011-01-24 5 views
0

Следующий запрос получает информацию, которая мне нужна. Тем не менее, я заметил, что по мере роста таблиц мой код становится медленнее и медленнее. Я предполагаю, что это этот запрос. Может ли это написать другой способ сделать его более эффективным? Я много слышал об использовании объединений вместо подзапросов, однако я не «получаю», как это сделать.Как оптимизировать этот запрос?

SELECT * FROM 

    (SELECT MAX(T.id) AS MAXid 
    FROM transactions AS T 
    GROUP BY T.position 
    ORDER BY T.position) AS result1, 

    (SELECT T.id AS id, T.symbol, T.t_type, T.degree, T.position, T.shares, T.price, T.completed, T.t_date, 
    DATEDIFF(CURRENT_DATE, T.t_date) AS days_past, 
    IFNULL(SUM(S.shares), 0) AS subtrans_shares, 
    T.shares - IFNULL(SUM(S.shares),0) AS due_shares, 

    (SELECT IFNULL(SUM(IF(SO.t_type = 'sell', -SO.shares, SO.shares)), 0) 
    FROM subtransactions AS SO WHERE SO.symbol = T.symbol) AS owned_shares 

    FROM transactions AS T 
    LEFT OUTER JOIN subtransactions AS S 
    ON T.id = S.transid  
    GROUP BY T.id 
    ORDER BY T.position) AS result2 

    WHERE MAXid = id 
+1

Можете ли вы публиковать операторы CREATE в таблице с индексами? –

ответ

0

Ваш код:

(SELECT MAX(T.id) AS MAXid 
    FROM transactions AS T  [<--- here ] 
    GROUP BY T.position 
    ORDER BY T.position) AS result1, 

    (SELECT T.id AS id, T.symbol, T.t_type, T.degree, T.position, T.shares, T.price, T.completed, T.t_date, 
    DATEDIFF(CURRENT_DATE, T.t_date) AS days_past, 
    IFNULL(SUM(S.shares), 0) AS subtrans_shares, 
    T.shares - IFNULL(SUM(S.shares),0) AS due_shares, 

    (SELECT IFNULL(SUM(IF(SO.t_type = 'sell', -SO.shares, SO.shares)), 0) 
    FROM subtransactions AS SO WHERE SO.symbol = T.symbol) AS owned_shares 

    FROM transactions AS T  [<--- here ] 

Обратите внимание на [<---- here ] метки, которые я добавил в свой код.

Первый T никоим образом не связан со вторым T. У них одинаковый псевдонимы корреляции, они относятся к одной и той же таблице, но они полностью независимы от выбора и результатов.

Так что вы делаете в первую, коррелированы, подзапрос получает максимальный идентификатор для всех positions в transactions.

И тогда вы присоединяетесь все transaction.position.max(id) с до result2 (который result2 случается объединение всех transaction.position с до subtransactions). (И внутренняя order by бессмысленно и дорого, тоже, но это не главная проблема.)

Вы присоединиться каждый transaction.position.max(id) к каждому (независимо от результата 2 выбирает).

На Edit, после возвращения домой: Хорошо, вы не Cartesianing, то "где MAXid = идентификатор" не присоединиться к result1result2. Но вы все еще сворачиваете все строки transaction в обоих запросах.

Таким образом, вы получаете декартову присоединиться - каждый result1 присоединился к каждому result2, безусловно (ничего не говорит базы данных, например, что они должны быть соединены (макс) ид или положением).

Итак, если у вас есть десять уникальных position.max(id) s в transaction, вы получаете 100 строк. 1000 уникальных позиций, миллион строк. И т. Д.

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

+0

Вы получите ужасную производительность с представлениями, хотя из-за использования агрегатной функции ('SUM()'). –

+0

Зависит от базы данных, Питер. В любом случае, лучше быть правильным и медленным, а затем оптимизировать медленнее, чем быстро и неправильно. – tpdi

+0

Я внес изменения, которые вы предложили, однако изменений в производительности не произошло. Оказывается, именно этот запрос не вызывал огромного замедления. Это еще один запрос, который вообще обращается к различным таблицам. :( – Drewneedshelp

0

Я бы разделил запрос на более мелкие куски, возможно, используя хранимую процедуру. Например, получите максимальные значения из транзакции и поместите это в переменную таблицы. Затем присоедините это к субтранзакциям. Это облегчит вам и компилятору работу над тем, что происходит. Кроме того, не зная, что индексы на вашем столе, трудно предложить больше советов

0

Вставьте контрольную функцию в код. Затем запустите каждую часть кода, чтобы определить, где происходит замедление. Часто замедление происходит в другом запросе, чем вы предполагаете. Определите правильный запрос, который необходимо оптимизировать, перед отправкой в ​​stackoverflow.

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