MySQL优化问题

时间:2011-08-08 23:13:00

标签: mysql database optimization

我遇到了查询优化问题。以下查询需要30秒以上才能获得预期结果。

SELECT tbl_history.buffet_q_rating, tbl_history.cod_stock, tbl_history.bqqq_change_month, stocks.ticker, countries.country, stocks.company
FROM tbl_history
INNER JOIN stocks ON tbl_history.cod_stock = stocks.cod_stock
INNER JOIN exchange ON stocks.cod_exchange = exchange.cod_exchange
INNER JOIN countries ON exchange.cod_country = countries.cod_country
WHERE exchange.cod_country =125
AND DATE = '2011-07-25'
AND bqqq_change_month IS NOT NULL 
AND buffet_q_rating IS NOT NULL 
ORDER BY bqqq_change_month DESC
LIMIT 10

表格是:

CREATE TABLE IF NOT EXISTS `tbl_history` (
`cod_stock` int(11) NOT NULL DEFAULT '0',
`date` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`price` decimal(11,3) DEFAULT NULL,
`buffet_q_rating` decimal(11,4) DEFAULT NULL,
`bqqq_change_day` decimal(11,2) DEFAULT NULL,
`bqqq_change_month` decimal(11,2) DEFAULT NULL,
(...)
PRIMARY KEY (`cod_stock`,`date`),
KEY `cod_stock` (`cod_stock`),
KEY `buf_rating` (`buffet_q_rating`),
KEY `data` (`date`),
KEY `bqqq_change_month` (`bqqq_change_month`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;

CREATE TABLE IF NOT EXISTS `stocks` (
`cod_stock` int(11) NOT NULL AUTO_INCREMENT,
`cod_exchange` int(11) DEFAULT NULL,
PRIMARY KEY (`cod_stock`),
KEY `exchangestocks` (`cod_exchange`),
KEY `codstock` (`cod_stock`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=0 ;

CREATE TABLE IF NOT EXISTS `exchange` (
`cod_exchange` int(11) NOT NULL AUTO_INCREMENT,
`exchange` varchar(100) DEFAULT NULL,
`cod_country` int(11) DEFAULT NULL,
PRIMARY KEY (`cod_exchange`),
KEY `countriesexchange` (`cod_country`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=0 ;

CREATE TABLE IF NOT EXISTS `countries` (
`cod_country` int(11) NOT NULL AUTO_INCREMENT,
`country` varchar(100) DEFAULT NULL,
`initial_amount` double DEFAULT NULL,
PRIMARY KEY (`cod_country`),
KEY `codcountry` (`cod_country`),
KEY `country` (`country`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=0 ;

第一个表有超过2000万行,第二个表有40k行,其他行只有几行(可能是100行)。

他们的问题似乎是“按顺序”,但我不知道如何优化它。 我已经尝试了一些搜索google / stackoverflow的东西,但我无法取得好成绩 有人可以给我一些建议吗?

修改 忘记了EXPLAIN结果:

id  select_type table   type    possible_keys   key key_len ref rows    Extra
1   SIMPLE  countries   const   PRIMARY,codcountry  PRIMARY 4   const   1   Using temporary; Using filesort
1   SIMPLE  exchange    ref PRIMARY,countriesexchange   countriesexchange   5   const   15  Using where
1   SIMPLE  stocks  ref PRIMARY,exchangestocks,codstock exchangestocks  5   databaseName.exchange.cod_exchange  661 Using where
1   SIMPLE  tbl_history eq_ref  PRIMARY,cod_stock,buf_rating,data,bqqq_change_mont...   PRIMARY 12  v.stocks.cod_stock,const    1   Using where

更新

这是我得到的新EXPLAIN:

id select_type table type   possible_keys                       key        key_len ref   rows Extra |
1  SIMPLE tbl_history range monthstats                          monthstats      14 NULL  80053 Using where; Using index |
1  SIMPLE countries   ref   country                             country          4 const     1 Using index |
1  SIMPLE exchange    ref   PRIMARY,cod_country,countryexchange countryexchange  5 cons‌​t     5 Using where; Using index |
1  SIMPLE stocks      ref   info4stats                          info4stats       9 databaseName.exchange.cod_exchange,d‌​atabaseName.stock_...                    1 Using where; Using index |

2 个答案:

答案 0 :(得分:1)

我会尝试以抢先的方式从125的国家记录开始并反向工作。通过使用Straight_join将强制查询的顺序为输入...

我还会在COD_Stock和DATE(date)的Tbl_History表上有一个索引。因此,查询将正确有效地匹配日期/时间字段的预限定日期部分的连接条件。

SELECT STRAIGHT_JOIN
      th.buffet_q_rating, 
      th.cod_stock, 
      th.bqqq_change_month, 
      stocks.ticker, 
      c.country, 
      s.company
   FROM 
      Exchange e
         join Countries c
            on e.Cod_Country = c.Cod_Country
         join Stocks s
            on e.cod_exchange = s.cod_exchange
            join tbl_history th
               on s.cod_stock = th.cod_stock
              AND th.`Date` = '2011-07-25'
              AND th.bqqq_change_month IS NOT NULL 
              AND th.buffet_q_rating IS NOT NULL 
   WHERE
      e.Cod_Country = 125
   ORDER BY 
      th.bqqq_change_month DESC
   LIMIT 10

答案 1 :(得分:0)

如果你想限制结果,为什么你加入所有表后呢? 在将其与其他表连接之前,首先尝试减小这些大表的大小(LIMIT或WHERE)。

但您必须确保原始查询和修改后的查询意味着相同。

更新(示例):

select
    tbl_user.user_id,
    tbl_group.group_name
from
    tbl_grp_user
inner join
(
    select
        tbl_user.user_id,
        tbl_user.user_name
    from
        tbl_user
    limit
        5
) as tbl_user
on
    tbl_user.user_id = tbl_grp_user.user_id
inner join
(
    select
        group_id,
        group_name
    from
        tbl_group
    where
        tbl_group.group_id > 5
) as tbl_group
on
    tbl_group.group_id = tbl_grp_user.group_id

希望上面的查询会给你一个提示