具實(shí)現(xiàn): jquery
addTextToDom : function(html,text){
var $t;
try{
$t=$(html);
if($t.length==0){//全中文
$t=$('<span>'+html+'</span>')
}
}catch(e){
//如果出現(xiàn)報(bào)錯(cuò),基本上可以確認(rèn)外層沒(méi)有包裹,增加一個(gè)p
$t=$('<p>'+html+'</p>');
}
var arr=[];
$t.each( function(index,item){
if(index > 0 ){
arr.push($(item));
}
});
var $first=$($t.get(0));
var $new=$('<span><span class="addT">'+text+'</span>'+$first.html()+'</span>');
return $new.get().map(a=>{return $(a).get(0).outerHTML;}).join('') + (arr.map(function(item){
return $(item).get(0).outerHTML;
}).join(''));
},
如果存在多個(gè)dom,則只添加第一個(gè),如果只有中文,則重新處理,添加外層包裹。
天給大家介紹兩個(gè)黑魔法,這都是壓箱底的法寶。大家在使用時(shí),一定要弄清他們的適用場(chǎng)景及用法,用好了,就是一把開(kāi)天斧,用不好那就是畫(huà)蛇添足。
可能有小伙伴會(huì)問(wèn),Covering Indexes到底是什么神器呢?它又是如何來(lái)提升性能的呢?接下來(lái)我會(huì)用最通俗易懂的語(yǔ)言來(lái)進(jìn)行介紹,畢竟不是每個(gè)程序猿都要像DBA那樣深刻理解數(shù)據(jù)庫(kù),知道如何用以及如何用好神器才是最關(guān)鍵的。
Covering Indexes(中文大都翻譯為“覆蓋索引”)就是一個(gè)索引覆蓋所有要查詢的字段(ps:這句話我挖個(gè)坑,文末我來(lái)解釋)。
An index that contains all required information to resolve the query is known as a “Covering Index” – it completely covers the query. Covering Index includes all the columns, the query refers to in the SELECT, JOIN, and WHERE clauses.
接下來(lái)我們通過(guò)一個(gè)非常簡(jiǎn)單的sql來(lái)進(jìn)行分析:
SELECT column1, column2 FROM tablename WHERE column3=xxx;
你能想象將sql的執(zhí)行時(shí)間從1.8秒,降到1.2秒,繼續(xù)壓榨到0.5,0.2…..,酣暢淋漓,怎一個(gè)爽字了得。就跟排兵布陣一樣,打勝仗固然重要,但得想出成本最低效果最好的陣法,定會(huì)收獲滿滿的成就感。
這條sql要如何來(lái)進(jìn)行優(yōu)化呢?第一反應(yīng)可能就是說(shuō)給“column3”加索引(普通索引或唯一索引)啊,沒(méi)錯(cuò),這樣確實(shí)能在很大程度上提升這條sql的性能。
我們來(lái)分析下上面sql的執(zhí)行計(jì)劃:因?yàn)榻o“column3”建了索引,就會(huì)快速根據(jù)這個(gè)索引查詢到符合條件的結(jié)果;然后再去這些符合條件的結(jié)果里查找所需的column1、column2字段;請(qǐng)注意,整個(gè)過(guò)程出現(xiàn)了兩次查詢,一次是查詢索引,另一次查詢結(jié)果的所需字段。簡(jiǎn)單點(diǎn)來(lái)說(shuō),就是根據(jù)column3找到符合條件的主鍵,然后根據(jù)主鍵找到該行數(shù)據(jù),即可找到所需的column1、column2。在這個(gè)過(guò)程中,回到主鍵索引樹(shù)搜索的過(guò)程,稱為回表。
那能不能將上面說(shuō)的執(zhí)行計(jì)劃再優(yōu)化一下呢?大殺器Covering Indexes就是用來(lái)干這事的。給column3、column1、column2建個(gè)復(fù)合索引,如下:
alter table table_name add index index_column3 (column3,column1,column2) ;
這樣就可以直接通過(guò)索引就能查詢出符合條件的數(shù)據(jù),而不必像上面那樣先去查索引,然后再去查數(shù)據(jù)的兩個(gè)過(guò)程。
由于覆蓋索引可以減少樹(shù)的搜索次數(shù),顯著提升查詢性能,所以使用覆蓋索引時(shí)一個(gè)常用的性能優(yōu)化手段。在高頻請(qǐng)求上用覆蓋索引,就不需回表查整行記錄,這樣可以顯著減少語(yǔ)句的執(zhí)行時(shí)間。
光說(shuō)不練那是假把式!小伙伴們可以用explain去試試上面的兩種情況,如果執(zhí)行復(fù)合索引后的情況,你會(huì)發(fā)現(xiàn)Extra里出現(xiàn)Using index。
剛開(kāi)始我說(shuō)挖了個(gè)坑,現(xiàn)在我把坑填上。既然神器Covering
Indexes這么好用,以后select語(yǔ)句的我都不管三七二十一的都亮出神器。難不成你select
*也要亮神器?一個(gè)表那么多字段,全建成索引?那索引文件會(huì)不堪重負(fù)的,這就會(huì)適得其反,帶來(lái)一系列惡果的。索引文件過(guò)大會(huì)造成insert、update非常慢,你select倒是爽快了,不能不顧其他兄弟吧,不仗義的事咱不能干,切記!
如果看完這個(gè)分析還不過(guò)癮,下面我給幾篇擴(kuò)展文章:
https://www.c-sharpcorner.com/UploadFile/b075e6/improving-sql-performance-using-covering-indexes/
https://www.red-gate.com/simple-talk/sql/learn-sql-server/using-covering-indexes-to-improve-query-performance/
https://stackoverflow.com/questions/609343/what-are-covering-indexes-and-covered-queries-in-sql-server
https://stackoverflow.com/questions/62137/what-is-a-covered-index
接下來(lái)給大家下另一個(gè)性能提升神器-STRAIGHT_JOIN,在數(shù)據(jù)量大的聯(lián)表查詢中靈活運(yùn)用的話,能大大縮短查詢時(shí)間。
首先來(lái)解釋下STRAIGHT_JOIN到底是用做什么的:
STRAIGHT_JOIN is similar to JOIN, except that the left table is always read before the right table. This can be used for those (few) cases for which the join optimizer puts the tables in the wrong order.
意思就是說(shuō)STRAIGHT_JOIN功能同join類似,但能讓左邊的表來(lái)驅(qū)動(dòng)右邊的表,能改表優(yōu)化器對(duì)于聯(lián)表查詢的執(zhí)行順序。
接下來(lái)我們舉個(gè)例子進(jìn)行大致的分析:
select t1.* from Table1 t1 inner join Table2 t2 on t1.CommonID=t2.CommonID where t1.FilterID=1
以上sql大數(shù)據(jù)量下執(zhí)行需要30s,是不是很奇怪?明明Table1表的FilterID字段建了索引啊,Table1和Table2的CommonID也建了索引啊。通過(guò)explain來(lái)分析,你會(huì)發(fā)現(xiàn)執(zhí)行計(jì)劃中表的執(zhí)行順序是Table2->Table1。這個(gè)時(shí)候要略微介紹下驅(qū)動(dòng)表的概念,mysql中指定了連接條件時(shí),滿足查詢條件的記錄行數(shù)少的表為驅(qū)動(dòng)表;如未指定查詢條件,則掃描行數(shù)少的為驅(qū)動(dòng)表。mysql優(yōu)化器就是這么粗暴以小表驅(qū)動(dòng)大表的方式來(lái)決定執(zhí)行順序的。
但如下sql的執(zhí)行時(shí)間都少于1s:
select t1.* from Table1 t1 where t1.FilterID=1
或
select t1.* from Table1 t1 inner join Table2 t2 on t1.CommonID=t2.CommonID
這個(gè)時(shí)候STRAIGHT_JOIN就派上用場(chǎng),我們對(duì)sql進(jìn)行改造如下:
select t1.* from Table1 t1 STRAIGHT_JOIN Table2 t2 on t1.CommonID=t2.CommonID where t1.FilterID=1
用explain進(jìn)行分析,發(fā)現(xiàn)執(zhí)行順序?yàn)門able1->Table2,這時(shí)就由Table1來(lái)作為驅(qū)動(dòng)表了,Table1中相應(yīng)的索引也就用上了,執(zhí)行時(shí)間竟然低于1s了。
分析到這里,必須要重點(diǎn)說(shuō)下:
擴(kuò)展閱讀:
https://stackoverflow.com/questions/512294/when-to-use-straight-join-with-mysql
https://stackoverflow.com/questions/5818837/why-does-straight-join-so-drastically-improve-this-query-and-what-does-it-mean
https://dev.mysql.com/doc/refman/8.0/en/join.html
*請(qǐng)認(rèn)真填寫(xiě)需求信息,我們會(huì)在24小時(shí)內(nèi)與您取得聯(lián)系。