2016-02-21 73 views
2

我目前正在研究一個財務應用程序。具有8列的MYSQL數據庫。 1百萬條記錄。MySql - 進一步查詢優化SELECT Where Where

插入:每分鐘30行。
更新:0
選擇:查詢 每200毫秒運行一次。每次執行返回大約200,000條記錄 。

選擇查詢,如下所示:是

SELECT COLUMNB, COLUMNC, COLUMND, COLUMNE FROM TABLE 
WHERE COLUMNE IN('ABCD','EFGH','IJKL','MNOP') 
ORDER BY COLUMNB DESC 

我的響應時間如下:執行:0.903秒抓取:0.2秒。

總計〜1.1秒

當我做一個解釋,我得到以下幾點:

ID,SELECT_TYPE,表,分區類型,possible_keys,鑰匙,key_len 'tbl_ColumnE_ColumnB,tbl_ColumnE',NULL,NULL, NULL,'1180834','34 .33',' ref,rows,filtered,Extra'1','SIMPLE','table',NULL,'ALL'運用哪裏;使用文件排序」

指標已處於活動狀態:

  1. tbl_ColumnE_ColumnB,
  2. tbl_ColumnB_ColumnE,
  3. tbl_ColumnE
  4. tbl_ColumnB

由於這是一個金融股市基地d應用程序。我需要將總執行時間進一步縮短到接近200毫秒或更少。有什麼我可以改進的?

已經完成:從8M

  1. innodb_buffer_pool增加到2000M(節省30%)
  2. 改變或運營商IN操作符(這是或之前節省了20%。)

顯示創建表格:

CREATE TABLE `tbl` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `COLUMNB` timestamp NULL DEFAULT NULL, 
    `COLUMNC` decimal(20,10) DEFAULT NULL, 
    `COLUMND` decimal(20,10) DEFAULT NULL, 
    `COLUMNX` decimal(20,10) DEFAULT NULL, 
    `COLUMNY` decimal(20,10) DEFAULT NULL, 
    `COLUMNZ` decimal(20,10) DEFAULT NULL, 
    `COLUMNE` varchar(45) DEFAULT NULL, 
    `COLUMNF` int(11) DEFAULT NULL, 
    PRIMARY KEY (`id`), 
    UNIQUE KEY `id_UNIQUE` (`id`), 
    KEY `tbl_ColumnE_ColumnB` (`ColumnE`,`ColumnB`), 
    KEY `tbl_ColumnB_ColumnE` (`ColumnB`,`ColumnE`), 
    KEY `tbl_ColumnB` (`ColumnB`), 
    KEY `tbl_ColumnE` (`ColumnE`) 
) ENGINE=InnoDB AUTO_INCREMENT=1718507 DEFAULT CHARSET=utf8' 
+0

查詢不使用索引:您必須在兩個字段(COLUMNE,COLUMNB)上創建一個複合索引,然後再次發送解釋 –

+0

@BerndBuffen已經有了! – Metaplace

+0

您的訂單條款是否必要? – sagi

回答

0

此問題ry:

SELECT COLUMNB, COLUMNC, COLUMND, COLUMNE 
FROM TABLE 
WHERE COLUMNE IN ('ABCD', 'EFGH', 'IJKL', 'MNOP') 
ORDER BY COLUMNB DESC; 

沒有便利的優化方法。問題是INORDER BY。對於IN列表中的單個值,最佳索引可能是(COLUMNE, COLUMNB, COLUMNC, COLUMND)(MySQL中的降序可能非常棘手)。

如果IN列表中的四個值是常量,我建議更改數據結構以使它們位於一列中。然後,此查詢:

SELECT COLUMNB, COLUMNC, COLUMND, COLUMNE 
FROM TABLE 
WHERE COLUMNEPRIME = 'ABCDEFGHIJKLMNOP' 
ORDER BY COLUMNB DESC; 

可以利用(COLUMNEPRIME, COLUMNB, COLUMNC, COLUMND, COLUMNE)上的索引。唉,在MySQL中,這可能需要使用會減慢插入的觸發器。

如果提取速度如此之快,您可能會發現在應用程序而不是數據庫中進行排序會更快。因此,請嘗試查詢:

SELECT COLUMNB, COLUMNC, COLUMND, COLUMNE 
FROM TABLE 
WHERE COLUMNE IN ('ABCD', 'EFGH', 'IJKL', 'MNOP'); 

使用四部分組合索引。

我注意到,在大多數情況下,每秒多次返回表的20%似乎沒有必要。也許有更好的方法來設計整個系統來做你需要的。

0

試試這個。 COLUMNE有多少種不同的數據?如果它不那麼困難,你也可以使用ENUM來加快查詢速度。 您也可以使用客戶端中的壓縮選項來最小化數據傳輸。

CREATE TEMPORARY TABLE `tbls` (
    `id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT, 
    `val` VARCHAR(45) DEFAULT NULL, 
    PRIMARY KEY (`id`), 
    KEY `val` (`val`) 
) ENGINE=INNODB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; 

INSERT INTO tbls (val) VALUES('ABCD'),('EFGH'),('IJKL'),('MNOP'); 

EXPLAIN 
SELECT COLUMNB, COLUMNC, COLUMND, COLUMNE FROM tbl 
INNER JOIN tbls ON tbl.COLUMNE = tbls.val 
ORDER BY COLUMNB DESC; 
0

行的百分比與IN匹配嗎?如果它超過20%,優化器將避開索引(以E開頭),因爲掃描整個表格可能會更快。

Sort(「filesort」)是必需的,因爲沒有辦法按正確的順序獲取行。你可以試試FORCE INDEX(ColumnB)

查詢花費這麼長時間的部分原因是您要返回200K行。思考一下你是否可以避免這種情況。

但是等等!如果你每2秒只插入一行,你爲什麼會認爲0.2秒後會有什麼變化?當你插入一行時,觸發重新計算(這個連接必須在應用程序中完成,不能完全在sql中完成)。這將導致更快的響應,因爲在下一次計算中您不會等待0.2秒。