加快mySQL SELECT查询,第一次查询比下一次查询需要1000倍?

时间:2017-04-18 14:43:29

标签: mysql

我有一个简单的ISAM表,有160万条记录。典型的查询在3个索引列上有一个WHERE子句,并返回10,000个左右的记录。出于这个问题的目的,我正在做SELECT *而我正在抛弃ORDER BY。关于该表的唯一不寻常的事情是它有一个大的非数字列VARCHAR(8192)。

对于我用于此问题的查询,第一次查询提交大约需要145秒,而后续提交大约需要2秒。该表在这种状态下毫无价值,因为我需要做的真正查询将在第一次提交时花费一个小时或更长时间。无论磁盘I / O做了多少,这看起来都很荒谬。当我使用INTO OUTFILE版本的查询时,mySQL可以在很短的时间内将大量文件写入磁盘......

如何修复此表?

#key_buffer_size=256M
#tmp_table_size=64M
#max_heap_table_size=64M
#myisam_sort_buffer_size=88M
#read_buffer_size=1M
#read_rnd_buffer_size=2M

回答问题:

表约为2.2GB 160万条记录。

速度:不需要速度快,速度足够快以避免在等待时死亡...现在需要5分钟才能接受2分钟。

EXPLAIN返回的信息:

mysql> EXPLAIN SELECT /*+ MAX_EXECUTION_TIME(200000)*/ *  
FROM tbl_skews 
WHERE (skw_minute IN(43)) 
  AND (tday_date >= 42767 AND tday_date <= 42838) 
  AND (skw_days > -10 AND skw_days < 70);

 id     1

 select_type     SIMPLE          
 table       tbl_skews     
 partitions      NULL           
 type    ref      
 possible_keys      ndx_skews_tday_date,ndx_skews_skw_minute,ndx_skews_skw_days     
 key                     ndx_skews_skw_minute     
 key_len        2    
 ref        const     
 rows       35396    
 filtered   1.51    
 Extra           Using where 

表格定义:

CREATE TABLE IF NOT EXISTS `spx_opts`.`tbl_skews` (    
`exp_true_date` INT NOT NULL,    
`exp_subndx` TINYINT NOT NULL,    
`tday_date` INT NOT NULL,    
`skw_minute` SMALLINT NOT NULL,    
`skw_TS_load` DOUBLE NOT NULL,    
`tday_days_to_next` SMALLINT NOT NULL,    
`tday_is_early_close` TINYINT NOT NULL,    
`tday_open_time` DOUBLE NOT NULL,    
`tday_close_time` DOUBLE NOT NULL,    
`prs_opar_pmod` SMALLINT NOT NULL,    
`prs_opar_yield` DOUBLE NOT NULL,    
`prs_best_yield` DOUBLE NOT NULL,    
`prs_best_pvdiv` DOUBLE NOT NULL,    
`prs_rate_libor` DOUBLE NOT NULL,    
`prs_rate_used` DOUBLE NOT NULL,    
`prs_rate_implied1` DOUBLE NOT NULL,    
`prs_rate_implied2` DOUBLE NOT NULL,    
`prs_TS_min` DOUBLE NOT NULL,    
`prs_TS_max` DOUBLE NOT NULL,    
`prs_is_exp_linked` TINYINT NOT NULL,    
`skw_is_chain_good` TINYINT NOT NULL,    
`skw_TS` DOUBLE NOT NULL,    
`skw_und_print` FLOAT NOT NULL,    
`skw_days` DOUBLE NOT NULL,    
`skw_ndx_m_pvdiv` DOUBLE NOT NULL,    
`skw_vol_atm` DOUBLE NOT NULL,    
`skw_cvix` DOUBLE NOT NULL,    
`skw_stk_vol` VARCHAR(8192) NOT NULL,    
PRIMARY KEY (`exp_true_date`, `exp_subndx`, `tday_date`, `skw_minute`),    
INDEX `ndx_skews_tday_date` (`tday_date`),    
INDEX `ndx_skews_skw_minute` (`skw_minute`),    
INDEX `ndx_skews_skw_days` (`skw_days`))    
ENGINE = MYISAM;

2 个答案:

答案 0 :(得分:0)

您可以尝试使用索引。索引类似于主键,但您可以在一个表中包含多个索引。

例如,如果我有以下查询

select * from users where email='christakos@gmail.com'

我必须为电子邮件列编制索引。

您可以观看此视频,详细了解索引https://www.youtube.com/watch?v=JjNef3tPltU

答案 1 :(得分:0)

skw_minute, tday_date, skw_days

创建composte索引
create index my_idx on my_table(skw_minute, tday_date, skw_days);