2017-04-18 48 views
-1

我有一個簡單的ISAM表,有160萬條記錄。典型的查詢在3個索引列上有一個WHERE子句,並返回10,000個左右的記錄。出於這個問題的目的,我在做SELECT *,而我將ORDER BY放在外面。關於表的唯一不尋常的事情是它有1個大的非數字列VARCHAR(8192)。加速mySQL SELECT查詢,第一個查詢需要比下一個要長1000倍?

對於我用於這個問題的查詢,第一個查詢提交大約需要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 

回答問題時:

表約1.6 2.2GB萬條記錄。

速度:不需要快速,只需足夠快,以避免在等待時死於老年......現在需要5分鐘才能接受2分鐘。

通過返回的信息說明:

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

第二次查詢始終將更快,因爲會得到從緩存中的數據。性能問題應該包括'EXPLAIN ANALYZE'和一些關於表格大小,索引,當前時間表現,期望時間等的信息。'Slow'是一個相對術語,我們需要一個實際值來比較。 \t \t [** MySQL **](http://dba.stackexchange.com/questions/15371/how-do-i-get-the-execution-plan-for-a-view) –

+0

問題被編輯回答問題... – dts

+0

編輯問題以使表格定義更清晰。 – dts

回答

0

創建composte指數skw_minute, tday_date, skw_days

create index my_idx on my_table(skw_minute, tday_date, skw_days); 
+0

好吧,組合索引是一個很大的進步......我的測試查詢時間從145秒變爲3秒。我不明白爲什麼額外的索引是必要的......我認爲我遵循了「足夠的索引,而不是太多」的最佳實踐。不幸的是,我每天需要運行的查詢仍需要90秒才能拉出44,000條記錄......還有什麼我可以做的嗎? – dts

+0

我不明白,你測試查詢在3秒內運行,但你有一個不同的查詢運行在90秒?什麼是查詢? PLAN在哪裏?您需要分析解釋計劃以瞭解查詢並對其進行優化。最佳實踐是解決問題的方法。如果你需要一個索引你創建該索引。在這裏檢查MySQL索引[** TIPS **](http://mysql.rjweb.org/doc.php/index_cookbook_mysql) –

+0

這是完全相同的查詢,只是具有更廣泛的日期範圍和skw_minute IN()而不是7個值1的價值......我永遠不能運行它,直到現在,因爲它會花費數小時。感謝提示鏈接,我會學習。 – dts

0

你可以嘗試使用索引。索引就像主鍵,但在一個表中可以有多個索引。

舉例來說,如果我有以下查詢

select * from users where email='[email protected]' 

我不得不指數的電子郵件列。

您可以觀看此視頻以瞭解更多有關索引https://www.youtube.com/watch?v=JjNef3tPltU

+0

OP說他已經在使用索引。 –

+0

確保您遵循以下步驟http://www.tocker.ca/2013/10/24/improving-the-performance-of-large-tables-in-mysql.html – cpap

+0

該列表主要關於innodb .. 。我用innodb啓動了這個項目,並轉移到isam,因爲innodb性能比isam差得多(請記住,我只關心讀取,而不是寫入......我的理解是isam通常對這種情況表現更好。) – dts