一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

MYSQL語句調(diào)優(yōu):MySQL語句排序分組后的結(jié)果

 Evilpot 2013-11-13
MySQL確實(shí)坑爹。分組后的結(jié)果是無法排序的。

現(xiàn)在有這樣的一種需求。假設(shè)表結(jié)構(gòu)為
 
CREATE TABLE `WCC_PM_Promotion_Product` (
  `PPPID` int(12) NOT NULL AUTO_INCREMENT, 
  `BRID` int(8) DEFAULT NULL ,
  `CTID` int(12) DEFAULT NULL ,
  `Price` decimal(16,2) DEFAULT NULL,
  `PKID` int(11) DEFAULT NULL,
  PRIMARY KEY (`PPPID`),
  KEY `index_brid` (`BRID`),
  KEY `index_ctid` (`CTID`),
  KEY `IDX_PKID` (`PKID`) USING BTREE,
) ENGINE=InnoDB AUTO_INCREMENT=1831273 DEFAULT CHARSET=utf8;

該表的數(shù)據(jù)量為70W+條。
現(xiàn)在有這樣的某PKID的記錄(PKID為變量,存在并發(fā)),需要取出在該條PKID和CTID為1時的BRID和PRICE。同時需要將BRID相同的條目中,最小的PRICE行取出來。

為了完成這樣的需求,很快就寫出了這樣的語句:
 SELECT WCC_PM_Promotion_Product.* FROM WCC_PM_Promotion_Product WHERE (WCC_PM_Promotion_Product.PKID='1342848') 
 AND (WCC_PM_Promotion_Product.CTID=1) GROUP BY WCC_PM_Promotion_Product.BRID ORDER BY WCC_PM_Promotion_Product.Price desc; 


這樣的語句可以將取出的條目分組。但是在分組后執(zhí)行ORDER BY 語句時并沒有對分組后的結(jié)果進(jìn)行排序。取出的不是我們想要的結(jié)果:
  

BRID為3的記錄中,并沒有取到最小值。也就是說GROUP BY語句并沒有對結(jié)果集進(jìn)行排序。

下面是沒有進(jìn)行分組及排序的結(jié)果集:

  
 

可以看出BRID取到的并不是最小PRICE值。


從MYSQL的手冊中可以知道,MYSQL的GROUP BY并不支持排序。那么怎么實(shí)現(xiàn)這一功能呢。
可以使用子查詢來實(shí)現(xiàn),于是上面的SQL語句被改寫為:

SELECT t.* FROM (SELECT * FROM WCC_PM_Promotion_Product WHERE (WCC_PM_Promotion_Product.PKID='1342848') 
AND (WCC_PM_Promotion_Product.CTID=1) ORDER BY WCC_PM_Promotion_Product.Price) as t GROUP BY t.BRID;

執(zhí)行結(jié)果為:

 
 
查詢執(zhí)行了0.02s??瓷先ッ菜撇诲e,性能OK同時還完成了需求。

但是一個只輸出3行的查詢,它的子查詢也只返回一個24行的結(jié)果集。為什么還會需要0.02s的時間?

于是想到了查詢可能存在性能問題。先看一下子查詢的執(zhí)行計劃:


 
發(fā)現(xiàn)執(zhí)行計劃中只掃描了107行,但是使用索引的同時還出現(xiàn)了Using filesort(索引外部排序)。出現(xiàn)這樣的情況的可能原因是ORDER BY 中的排序列沒有索引。
于是,
處理1.在PRICE列上建立單獨(dú)的索引。執(zhí)行上述執(zhí)行計劃,發(fā)現(xiàn)結(jié)果同上面的結(jié)果完全一致。也就是說子查詢并沒有使用IDX_PRICE這個索引。甚至沒有將其作為備選鍵。

處理2.建立聯(lián)合索引IDX_PRICE_PKID。執(zhí)行計劃顯示子查詢同樣沒有使用該索引。FORCE INDEX(IDX_PRICE_PKID)語句強(qiáng)制使用該索引會引發(fā)更糟糕的性能,如下圖,70W行數(shù)據(jù)被掃描了68W行。

 
 
這一結(jié)果想到聯(lián)合索引的使用還和索引中列的順序有關(guān)。
于是,
處理3.更換了聯(lián)合索引中的列的位置,IDX_PKID_PRICE。繼續(xù)強(qiáng)制使用該索引,執(zhí)行后發(fā)現(xiàn)掃描行數(shù)與單獨(dú)使用IDX_PKID索引一致,但是沒有了使用外部索引排序的問題(Using filesort)。如下圖:


下面我們執(zhí)行以下原查詢語句在加入該索引后的執(zhí)行計劃。如下圖:

  
 
子查詢的結(jié)果正常了。但是外查詢中出現(xiàn)了Using temporary和Using filesort。同時出現(xiàn)兩大性能瓶頸。特別是使用臨時表,當(dāng)數(shù)據(jù)量很大的時候會加大CPU的負(fù)載,形成大量的鎖表,導(dǎo)致無法插入修改及查詢數(shù)據(jù)。然而我們的需求導(dǎo)致無法完全解決使用臨時表的問題,因此應(yīng)該盡量的減少內(nèi)查詢的消耗。讓其盡量的少掃描表中的行。

分析可知,只有24行的子查詢卻掃描了107行也不是很正常。所以,在索引IDX_PKID_PRICE的基礎(chǔ)上,再加入WHERE 語句中出現(xiàn)的CTID,將原本應(yīng)該使用的CTID上的索引起作用。

 
 
終于,子查詢的掃描行被控制在了結(jié)果集內(nèi)。這樣原查詢即便使用了臨時表也不會形成太大了性能開銷。如圖,原本需要0.02s的查詢被限制在了0.00s內(nèi)。雖然沒有看profile,但是相信不會有問題的(心態(tài)就是這么好~哈哈哈~)。

 
 

結(jié)論:

SQL語句的調(diào)優(yōu),首先要分析任務(wù)計劃。在出現(xiàn)USING FILESORT和USING TEMPORARY時,應(yīng)考慮一下是不是ORDER BY語句中的字段沒有出現(xiàn)在SELECT從句,從而導(dǎo)致了優(yōu)化器使用了外部排序。
當(dāng)查詢掃描的表行數(shù)太多時,應(yīng)考慮一下是否因?yàn)椴樵冏侄紊蠜]有索引。需要時要建立聯(lián)合索引。但是聯(lián)合索引在創(chuàng)建時要考慮使用索引的順序。


By Pottieva.Zhang
2013.11.13

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多

    五月婷婷六月丁香在线观看 | 人人妻人人澡人人夜夜| 国产日韩欧美一区二区| 激情亚洲内射一区二区三区| 日韩一区二区三区在线日| 欧洲日本亚洲一区二区| 欧美亚洲三级视频在线观看| 日本精品免费在线观看| 亚洲香艳网久久五月婷婷| 91麻豆精品欧美视频| 日韩人妻一区中文字幕| 麻豆蜜桃星空传媒在线观看| 伊人久久青草地婷婷综合| 国产精品亚洲欧美一区麻豆| 夜夜嗨激情五月天精品| 欧美自拍系列精品在线| 亚洲一级在线免费观看| 国产传媒一区二区三区| 美国欧洲日本韩国二本道| 亚洲高清欧美中文字幕| 大香蕉网国产在线观看av| 日本乱论一区二区三区| 男人操女人下面国产剧情| 高清在线精品一区二区| 中国美女草逼一级黄片视频| 亚洲日本中文字幕视频在线观看 | 欧美国产精品区一区二区三区| 国产日韩久久精品一区| 丝袜av一区二区三区四区五区| 国产成人亚洲欧美二区综| 国产欧美日产久久婷婷| 中文字字幕在线中文乱码二区| 国产精品久久三级精品| 国产不卡最新在线视频| 欧美精品亚洲精品日韩专区| 午夜成年人黄片免费观看| 国产日韩精品欧美综合区| 国产精品一区二区日韩新区| 国产成人精品资源在线观看| 亚洲一区二区三区一区| 国产精品香蕉在线的人|