Audrius Gailius
Audrius Gailius

Reputation: 68

Mysql optimization: Can someone expalain why one query is working faster than inner join

So there are two queries. Why first is running much faster than second? How can I optimize my inner join to be as fast as the first one ?

Total records more than 4 000 000

idTerminals is indexed


select (select name 
          from terminals 
          where terminals.idTerminals = AnalyzeProfitResults.idTerminals),
        currency, 
        count(*) 
from AnalyzeProfitResults
group by AnalyzeProfitResults.idTerminals,currency;


select name,
        currency, 
        count(*) 
from AnalyzeProfitResults
inner join terminals on terminals.idTerminals = AnalyzeProfitResults.idTerminals
group by AnalyzeProfitResults.idTerminals,currency;

    

the results are same:


name,currency,count(*)
"Buy or sell",EURUSD,235105
"Buy or sell",GBPUSD,14515
"Buy or sell",USDJPY,235298
"very strict",AUDJPY,234787
"very strict",AUDUSD,235298
"very strict",CHFJPY,235298
"very strict",EURJPY,235298
"very strict",EURUSD,235298
"very strict",GBPJPY,235298
"very strict",GBPUSD,235298
"very strict",NZDUSD,235298
"very strict",USDCHF,235298
"very strict",USDJPY,235298
",normal",AUDJPY,235298
",normal",AUDUSD,36391
",normal",EURUSD,234985
",normal",GBPJPY,117649
",normal",NZDUSD,198552
",normal",USDCHF,235298
",normal",USDJPY,235298
 

Upvotes: 0

Views: 82

Answers (1)

Simon
Simon

Reputation: 12478

I suppose in the latter query, MySQL joins AnalyzeProfitResults and terminals which yields size(AnalyzeProfitResults) * size(terminals) rows for the group by operation. With 4 million rows in AnalyzeProfitResults, that's a lot of rows even if terminals contains just a handful of records. In the former case, MySQL performs the grouping on 4 million rows which yields the 20ish rows you gave as result, and only then performs a subquery for each of the 20 rows (which might even be rewritten to a join internally, that would be even faster).

edit: Here's the first query with an explicit join:

select terminals.name, APR_aggregated.*
from terminals join (
    select APR.currency, count(*)
    from AnalyzeProfitResults as APR
    group by APR.idTerminals, APR.currency
) as APR_aggregated on terminals.idTerminals = APR_aggregated.idTerminals

Upvotes: 1

Related Questions