List:General Discussion« Previous MessageNext Message »
From:Michael Widenius Date:April 29 1999 12:31am
Subject:Help with a join select
View as plain text  
>>>>> "Shane" == Shane Wegner <shane@stripped> writes:

Shane> Hi all,
Shane> I am not sure if this is the appropriate place to ask about this and
Shane> appologise if it isn't.  I am having problems with a select in that it
Shane> works but is much slower than any other select.  It uses indexes as well
Shane> so I am at a loss as to why this is the case.

Shane> The select is supposed to return the last 30 closing values for a symbol
Shane> where the last value is on the date given.  The following tables are
Shane> involved (stripped for this email of corse).

Shane> create table symdata(
Shane> id bigint default 0 not null auto_increment,
Shane> symbol_id int default 0 not null,
Shane> date_id smallint default 0 not null,
Shane> close double(22,3) default 0 not null,
Shane> primary key(id),
Shane> index id_index(date_id,symbol_id)
Shane> );

Shane> create table symbol(
Shane> id int default 0 not null auto_increment,
Shane> symbol varchar(10) default '' not null,
Shane> primary key(id),
Shane> index id_and_symbol_index(id,symbol)
Shane> );

Shane> create table _date(
Shane> id smallint default 0 not null auto_increment,
Shane> _date date default 0 not null,
Shane> primary key(id),
Shane> index id_and_date_index(id,_date)
Shane> );

Shane> So to get the last 30 closing values for symbol BCE as of Jun 1, 1998, I
Shane> do the following select.

Shane> select symdata.close from symdata, symbol, _date where symdata.symbol_id =
Shane> symbol.id and symbol.symbol = 'bce' and symdata.date_id = _date.id and
Shane> to_days(_date._date) <= to_days('1998-06-01') order by _date._date desc
Shane> limit 30

Shane> It takes approximately 30 seconds.  symdata has about 2,000,000 entries
Shane> and symbol about 6,000 entries.

mysql> explain select symdata.close from symdata, symbol, _date where
Shane> symdata.symbol_id =
-> symbol.id and symbol.symbol = 'bce' and symdata.date_id = _date.id
Shane> and
-> to_days(_date._date) <= to_days('1998-06-01') order by _date._date
Shane> desc
-> limit 30
-> \g
Shane>
> +---------+--------+---------------------------------------------------+---------+---------+-----------------+---------+--------------------------------+
Shane> | table   | type   | possible_keys                                     |
Shane> key     | key_len | ref             | rows    | Extra
Shane> |
Shane>
> +---------+--------+---------------------------------------------------+---------+---------+-----------------+---------+--------------------------------+
Shane> | symbol  | range  | PRIMARY,symbol_index,id_index,id_and_symbol_index |
Shane> NULL    |    NULL | NULL            |       1 | range used on key
Shane> symbol_index |
Shane> | symdata | ALL    | NULL                                              |
Shane> NULL    |    NULL | NULL            | 2772635 | where used
Shane> |
Shane> | _date   | eq_ref | PRIMARY,id_index,id_and_date_index                |
Shane> PRIMARY |       2 | symdata.date_id |       1 | where used
Shane> |
Shane>
> +---------+--------+---------------------------------------------------+---------+---------+-----------------+---------+--------------------------------+
Shane> 3 rows in set (0.03 sec)


Shane> It looks alright but perhapse there is something I am overlooking here.
Shane> If anyone has any suggestions, I would really appreciate them.

Hi!

The problem is the second 'ALL' in the 'type' column;  MySQL has to
scan through all rows in symdata (for each possible value in symbol)!

Note that as long as you use 'todays()', MySQL can't use the date key!

Another problem is that _date.id is not defined exactly as 'symdata.date_id'

Try fixing the fields to have identical types and use the following query:

select symdata.close from symdata, symbol, _date where symdata.symbol_id =
symbol.id and symbol.symbol = 'bce' and symdata.date_id = _date.id and
_date._date <= 1998-06-01' order by _date._date desc
limit 30

Are you by the way sure that the query shouldn't be:

select symdata.close from symdata, symbol, _date where symdata.symbol_id =
symbol.id and symbol.symbol = 'bce' and symdata.date_id = _date.date_id and
_date._date <= 1998-06-01' order by _date._date desc
limit 30

Regards,
Monty
Thread
Help with a join selectShane Wegner29 Apr
  • Help with a join selectMichael Widenius29 Apr