К багрепорту приложен SQL-запрос, который долго выполняется (12 секунд на тестовом сервере). Вот такой вот запрос:
SELECT txt.taAttrValue AS `name`, mrins.Currency AS currency, mCode AS exchange, tsLastPrice AS price, tsNetCh AS `change`, tsNetChPercent AS `change-pers`, subgrp.taAttrValue AS subgroup, ord.taAttrValue AS instrOrder, trsess.MarketId AS marketId, trsess.tsTicker AS ticker FROM sfcTradeSession AS trsess JOIN sfcMarketInstrument AS mrins ON mrins.MarketId = trsess.MarketId AND mrins.miTicker = trsess.tsTicker JOIN sfcMarket AS mrkt ON mrins.MarketId = mrkt.mId JOIN sfcTradeInstrument AS trins ON mrins.InstrumentId = trins.tiId JOIN sfcTradeInstrumentAttribute AS txt ON trins.tiId = txt.InstrumentId AND txt.taAttrName = "name" JOIN sfcTradeInstrumentAttribute AS cntrgrp ON trins.tiId = cntrgrp.InstrumentId AND cntrgrp.taAttrName = "countryGroup" JOIN sfcTradeInstrumentAttribute AS instgrp ON trins.tiId = instgrp.InstrumentId AND instgrp.taAttrName = "group" LEFT JOIN sfcTradeInstrumentAttribute AS subgrp ON trins.tiId = subgrp.InstrumentId AND subgrp.taAttrName = "subgroup" LEFT JOIN sfcTradeInstrumentAttribute AS ord ON trins.tiId = ord.InstrumentId AND ord.taAttrName = "order" WHERE trsess.tsDate = ( SELECT tsDate AS tsDate FROM sfcTradeSession AS intsess WHERE intsess.tsTicker = trsess.tsTicker ORDER BY tsDate DESC LIMIT 1 ) AND trins.tiType = "commodity" AND cntrgrp.taAttrValue LIKE "Ukraine" AND instgrp.taAttrValue = "energy prices" AND subgrp.taAttrValue = "oil/gas" ORDER BY cast(instrOrder as signed) ASC;
Пиздец, правда?
Но я же профессионал. Я могу работать с любым говнокодом, если потребуется. Начинаю разбираться и нахожу, что источник тормозов — вложенный SELECT во WHERE, который выполняется по разу на каждую потенциальную строку результатов (а всего в таблице sfcTradeSession, по которой идёт выборка и которая используется в этом же SELECTе, порядка 100К строк и со временем будет на два порядка больше).
Решение получается быстро. Делаем VIEW с результатами, заменяющими тот вложенный SELECT:
CREATE VIEW vwTradeSessionEnd AS SELECT MAX(tsDate) AS tsDate, tsTicker FROM sfcTradeSession GROUP BY tsTicker;
...и используем его:
--- bug492 2009-05-14 13:46:29.000000000 +0300 +++ fix492 2009-05-14 16:48:23.000000000 +0300 @@ -23,17 +23,18 @@ subgrp.InstrumentId AND subgrp.taAttrName = "subgroup" LEFT JOIN sfcTradeInstrumentAttribute AS ord ON trins.tiId = ord.InstrumentId AND ord.taAttrName = "order" - WHERE trsess.tsDate = - ( - SELECT tsDate AS tsDate - FROM sfcTradeSession AS intsess - WHERE intsess.tsTicker = trsess.tsTicker - ORDER BY tsDate DESC - LIMIT 1 - ) AND + LEFT JOIN vwTradeSessionEnd AS tse ON tse.tsTicker=trsess.tsTicker + WHERE trsess.tsDate = tse.tsDate AND trins.tiType = "commodity" AND cntrgrp.taAttrValue LIKE "Ukraine" AND instgrp.taAttrValue = "energy prices" AND subgrp.taAttrValue = "oil/gas"
SELECT, на котором построен VIEW, выполняется ~0.8 секунд. Новый вариант запроса выполняется за 0.85 секунд, из которых 0.8 съедает этот VIEW. Короче, в качестве временного решения подойдёт.
Остаётся одна небольшая проблемка — надо внести изменения в код проекта. Начинаю искать этот SQL-запрос в коде.
Нахожу, откуда он берётся.
Бляяя.
$condition = exp::_('trsess.sessionDate') ->eq(exp::open( SqlQuery::select(array(TradeSessionModel::TABLE, 'intsess'), DBConn::GetInstance()) ->useMap(BaseModelClass::create(TradeSessionModel::MODEL)->getPropMap()) ->field('sessionDate') ->where('intsess.ticker = trsess.ticker') ->order('sessionDate', 'DESC') ->limit(1) )->close()) ->land()->_('trins.type')->eq($this->instrumentType) ->land()->_('cntrgrp.attrValue')->like($this->countryGroup) ->land()->_('instgrp.attrValue')->eq($this->instrumentGroup); if (null != $this->selectedIndex) { $condition = $condition->land()->_('trsess.ticker')->eq($this->selectedIndex); } if (null != $this->subgroup) { $condition = $condition->land()->_('subgrp.attrValue')->eq($this->subgroup); } $attrName = ('en' == $this->language) ? 'name' : 'name_'.$this->language; $query = SqlQuery::select(array(TradeSessionModel::TABLE, 'trsess'), DBConn::GetInstance()) ->useMap(BaseModelClass::create(TradeSessionModel::MODEL)->getPropMap()) ->useMap(BaseModelClass::create(TradeInstrumentModel::MODEL)->getPropMap(), 'trins') ->useMap(BaseModelClass::create(MarketInstrumentModel::MODEL)->getPropMap(), 'mrins') ->useMap(BaseModelClass::create(MarketModel::MODEL)->getPropMap(), 'mrkt') ->useMap(BaseModelClass::create(TradeInstrumentAttrModel::MODEL)->getPropMap(), 'txt') ->useMap(BaseModelClass::create(TradeInstrumentAttrModel::MODEL)->getPropMap(), 'cntrgrp') ->useMap(BaseModelClass::create(TradeInstrumentAttrModel::MODEL)->getPropMap(), 'instgrp') ->useMap(BaseModelClass::create(TradeInstrumentAttrModel::MODEL)->getPropMap(), 'subgrp') ->useMap(BaseModelClass::create(TradeInstrumentAttrModel::MODEL)->getPropMap(), 'ord') ->join(array(MarketInstrumentModel::TABLE, 'mrins'), 'mrins.marketId = trsess.marketId AND mrins.ticker = trsess.ticker') ->join(array(MarketModel::TABLE, 'mrkt'), 'mrins.marketId = mrkt.id') ->join(array(TradeInstrumentModel::TABLE, 'trins'), 'mrins.instrumentId = trins.id') ->join(array(TradeInstrumentAttrModel::TABLE, 'txt'), 'trins.id = txt.instrumentId AND txt.attrName = ?', $attrName) ->join(array(TradeInstrumentAttrModel::TABLE, 'cntrgrp'), 'trins.id = cntrgrp.instrumentId AND cntrgrp.attrName = ?', 'countryGroup') ->join(array(TradeInstrumentAttrModel::TABLE, 'instgrp'), 'trins.id = instgrp.instrumentId AND instgrp.attrName = ?', 'group') ->leftJoin(array(TradeInstrumentAttrModel::TABLE, 'subgrp'), 'trins.id = subgrp.instrumentId AND subgrp.attrName = ?', 'subgroup') ->leftJoin(array(TradeInstrumentAttrModel::TABLE, 'ord'), 'trins.id = ord.instrumentId AND ord.attrName = ?', 'order') ->field('txt.attrValue', '`name`') ->field('mrins.currency') ->field('marketCode', 'exchange') ->field('lastPrice', 'price') ->field('netChange', '`change`') ->field('netChangePercent', '`change-pers`') ->field('subgrp.attrValue', 'subgroup') ->field('ord.attrValue', 'instrOrder') ->field('trsess.marketId') ->field('trsess.ticker') ->where($condition) ->order('cast(instrOrder as signed)');
Ебала жаба гадюку.