К багрепорту приложен 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)');Ебала жаба гадюку.