第一篇:select語(yǔ)句性能優(yōu)化小結(jié)
對(duì)查詢進(jìn)行優(yōu)化,應(yīng)盡量避免全表掃描,首先應(yīng)考慮在 where 及 order by 涉及的列上建立索引。
2.應(yīng)盡量避免在 where 子句中對(duì)字段進(jìn)行 null 值判斷,否則將導(dǎo)致引擎放棄使用索引而進(jìn)行全表掃描,如:
select id from t where num is null
可以在num上設(shè)置默認(rèn)值0,確保表中num列沒(méi)有null值,然后這樣查詢:
select id from t where num=0
3.應(yīng)盡量避免在 where 子句中使用!=或<>操作符,否則將引擎放棄使用索引而進(jìn)行全表掃描。
4.應(yīng)盡量避免在 where 子句中使用 or 來(lái)連接條件,否則將導(dǎo)致引擎放棄使用索引而進(jìn)行全表掃描,如:
select id from t where num=10 or num=20 可以這樣查詢:
select id from t where num=10 union all
select id from t where num=20
5.in 和 not in 也要慎用,否則會(huì)導(dǎo)致全表掃描,如: select id from t where num in(1,2,3)
對(duì)于連續(xù)的數(shù)值,能用 between 就不要用 in 了:
select id from t where num between 1 and 3
6.下面的查詢也將導(dǎo)致全表掃描:
select id from t where name like '%abc%' 若要提高效率,可以考慮全文檢索。
7.如果在 where 子句中使用參數(shù),也會(huì)導(dǎo)致全表掃描。因?yàn)镾QL只有在運(yùn)行時(shí)才會(huì)解析局部變量,但優(yōu)化程序不能將訪問(wèn)計(jì)劃的選擇推遲到運(yùn)行時(shí);它必須在編譯時(shí)進(jìn)行選擇。然而,如果在編譯時(shí)建立訪問(wèn)計(jì)劃,變量的值還是未知的,因而無(wú)法作為索引選擇的輸入項(xiàng)。如下面語(yǔ)句將進(jìn)行全表掃描:
select id from t where num=@num 可以改為強(qiáng)制查詢使用索引:
select id from t with(index(索引名))where num=@num
8.應(yīng)盡量避免在 where 子句中對(duì)字段進(jìn)行表達(dá)式操作,這將導(dǎo)致引擎放棄使用索引而進(jìn)行全表掃描。如:
select id from t where num/2=100 應(yīng)改為:
select id from t where num=100*2
9.應(yīng)盡量避免在where子句中對(duì)字段進(jìn)行函數(shù)操作,這將導(dǎo)致引擎放棄使用索引而進(jìn)行全表掃描。如:
select id from t where substring(name,1,3)='abc'--name以abc開頭的id select id
from
t
where datediff(day,createdate,'2005-11-30')=0--?2005-11-30?生成的id 應(yīng)改為:
select id from t where name like 'abc%' select id from
t
where
createdate>='2005-11-30'
and createdate<'2005-12-1'
10.不要在 where 子句中的“=”左邊進(jìn)行函數(shù)、算術(shù)運(yùn)算或其他表達(dá)式運(yùn)算,否則系統(tǒng)將可能無(wú)法正確使用索引。
11.在使用索引字段作為條件時(shí),如果該索引是復(fù)合索引,那么必須使用到該索引中的第一個(gè)字段作為條件時(shí)才能保證系統(tǒng)使用該索引,否則該索引將不會(huì)被使用,并且應(yīng)盡可能的讓字段順序與索引順序相一致。
12.不要寫一些沒(méi)有意義的查詢,如需要生成一個(gè)空表結(jié)構(gòu):
select col1,col2 into #t from t where 1=0
這類代碼不會(huì)返回任何結(jié)果集,但是會(huì)消耗系統(tǒng)資源的,應(yīng)改成這樣: create table #t(...)
13.很多時(shí)候用 exists 代替 in 是一個(gè)好的選擇:
select num from a where num in(select num from b)用下面的語(yǔ)句替換:
select num from a where exists(select 1 from b where num=a.num)
14.并不是所有索引對(duì)查詢都有效,SQL是根據(jù)表中數(shù)據(jù)來(lái)進(jìn)行查詢優(yōu)化的,當(dāng)索引列有大量數(shù)據(jù)重復(fù)時(shí),SQL查詢可能不會(huì)去利用索引,如一表中有字段sex,male、female幾乎各一半,那么即使在sex上建了索引也對(duì)查詢效率起不了作用。
15.索引并不是越多越好,索引固然可以提高相應(yīng)的 select 的效率,但同時(shí)也降低了 insert 及 update 的效率,因?yàn)?insert 或 update 時(shí)有可能會(huì)重建索引,所以怎樣建索引需要慎重考慮,視具體情況而定。一個(gè)表的索引數(shù)最好不要超過(guò)6個(gè),若太多則應(yīng)考慮一些不常使用到的列上建的索引是否有必要。詳細(xì)講解提高數(shù)據(jù)庫(kù)查詢效率的實(shí)用方法
16.應(yīng)盡可能的避免更新 clustered 索引數(shù)據(jù)列,因?yàn)?clustered 索引數(shù)據(jù)列的順序就是表記錄的物理存儲(chǔ)順序,一旦該列值改變將導(dǎo)致整個(gè)表記錄的順序的調(diào)整,會(huì)耗費(fèi)相當(dāng)大的資源。若應(yīng)用系統(tǒng)需要頻繁更新 clustered 索引數(shù)據(jù)列,那么需要考慮是否應(yīng)將該索引建為 clustered 索引。
17.盡量使用數(shù)字型字段,若只含數(shù)值信息的字段盡量不要設(shè)計(jì)為字符型,這會(huì)降低查詢和連接的性能,并會(huì)增加存儲(chǔ)開銷。這是因?yàn)橐嬖谔幚聿樵兒瓦B接時(shí)會(huì)逐個(gè)比較字符串中每一個(gè)字符,而對(duì)于數(shù)字型而言只需要比較一次就夠了。
18.盡可能的使用 varchar/nvarchar 代替 char/nchar,因?yàn)槭紫茸冮L(zhǎng)字段存儲(chǔ)空間小,可以節(jié)省存儲(chǔ)空間,其次對(duì)于查詢來(lái)說(shuō),在一個(gè)相對(duì)較小的字段內(nèi)搜索效率顯然要高些。
19.任何地方都不要使用 select * from t,用具體的字段列表代替“*”,不要返回用不到的任何字段。
20.盡量使用表變量來(lái)代替臨時(shí)表。如果表變量包含大量數(shù)據(jù),請(qǐng)注意索引非常有限(只有主鍵索引)。
21.避免頻繁創(chuàng)建和刪除臨時(shí)表,以減少系統(tǒng)表資源的消耗。
22.臨時(shí)表并不是不可使用,適當(dāng)?shù)厥褂盟鼈兛梢允鼓承├谈行?,例如,?dāng)需要重復(fù)引用大型表或常用表中的某個(gè)數(shù)據(jù)集時(shí)。但是,對(duì)于一次性事件,最好使用導(dǎo)出表。
23.在新建臨時(shí)表時(shí),如果一次性插入數(shù)據(jù)量很大,那么可以使用 select into 代替 create table,避免造成大量 log,以提高速度;如果數(shù)據(jù)量不大,為了緩和系統(tǒng)表的資源,應(yīng)先create table,然后insert。
24.如果使用到了臨時(shí)表,在存儲(chǔ)過(guò)程的最后務(wù)必將所有的臨時(shí)表顯式刪除,先 truncate table,然后 drop table,這樣可以避免系統(tǒng)表的較長(zhǎng)時(shí)間鎖定。
25.盡量避免使用游標(biāo),因?yàn)橛螛?biāo)的效率較差,如果游標(biāo)操作的數(shù)據(jù)超過(guò)1萬(wàn)行,那么就應(yīng)該考慮改寫。
26.使用基于游標(biāo)的方法或臨時(shí)表方法之前,應(yīng)先尋找基于集的解決方案來(lái)解決問(wèn)題,基于集的方法通常更有效。
27.與臨時(shí)表一樣,游標(biāo)并不是不可使用。對(duì)小型數(shù)據(jù)集使用 FAST_FORWARD 游標(biāo)通常要優(yōu)于其他逐行處理方法,尤其是在必須引用幾個(gè)表才能獲得所需的數(shù)據(jù)時(shí)。在結(jié)果集中包括“合計(jì)”的例程通常要比使用游標(biāo)執(zhí)行的速度快。如果開發(fā)時(shí)間允許,基于游標(biāo)的方法和基于集的方法都可以嘗試一下,看哪一種方法的效果更好。
28.在所有的存儲(chǔ)過(guò)程和觸發(fā)器的開始處設(shè)置 SET NOCOUNT ON,在結(jié)束時(shí)設(shè)置 SET NOCOUNT OFF。無(wú)需在執(zhí)行存儲(chǔ)過(guò)程和觸發(fā)器的每個(gè)語(yǔ)句后向客戶端發(fā)送 DONE_IN_PROC 消息。
29.盡量避免大事務(wù)操作,提高系統(tǒng)并發(fā)能力。
30.盡量避免向客戶端返回大數(shù)據(jù)量,若數(shù)據(jù)量過(guò)大,應(yīng)該考慮相應(yīng)需求是否合理。
1.對(duì)查詢進(jìn)行優(yōu)化,應(yīng)盡量避免全表掃描,首先應(yīng)考慮在 where 及 order by 涉及的列上建立索引。
2.應(yīng)盡量避免使用 left join 和 null 值判斷。left join 比 inner join 消耗更多的資源,因?yàn)樗鼈儼c null(不存在)數(shù)據(jù)匹配的數(shù)據(jù),所以如果可以重新編寫查詢以使得該查詢不使用任何 inner join,則會(huì)得到相應(yīng)的回報(bào)。
例如有兩表: product(product_id int not null,product_type_id int null,...),產(chǎn)品表,product_id 為大于0的整數(shù),product_type_id 與表 product_type 關(guān)聯(lián),但可為空,因?yàn)橛械漠a(chǎn)品沒(méi)有類別
product_type(product_type_id not null,product_type_name null,...),產(chǎn)品類別表
此時(shí)要關(guān)聯(lián)兩表后查詢 product 的內(nèi)容,馬上會(huì)想到使用 inner join,但下面有一種方法可避免使用 inner join :
在 product_type 中增加一條記錄:0,'',...,并將 product 的 product_type_id 設(shè)置為 not null,當(dāng)產(chǎn)品沒(méi)有類別時(shí)將其 product_type_id 設(shè)為0,這樣查詢就可以使用 inner join 了。
3.應(yīng)盡量避免在 where 子句中使用!=或<>操作符,否則引擎可能放棄使用索引而進(jìn)行全表掃描。
4.應(yīng)盡量避免在 where 子句中使用 or 來(lái)連接條件,否則將可能導(dǎo)致引擎放棄使用索引而進(jìn)行全表掃描,如有表 t,key1、key2 上建有索引,需要下面的存儲(chǔ)過(guò)程:
create procedure select_proc1 @key1 int=0,@key2 int=0 as begin
select key3 from t
where(@key1=0 or key1=@key1)and(@key2=0 or key2=@key2)end go
這個(gè)存儲(chǔ)過(guò)程會(huì)導(dǎo)致全表掃描,可作如下修改:
create procedure select_proc2 @key1 int=0,@key2 int=0 as begin
if @key1 <>0 and @key2<>0 select key3 from t
where key1=@key1 and key2=@key2 else
if @key1<>0
select key3 from t where key1=@key1 else
select key3 from t where key2=@key2 end go
更改后雖然代碼增加了,但效率提高了。
5.in 和 not in 也要慎用,如:
select id from t where num in(1,2,3)
對(duì)于連續(xù)的數(shù)值,能用 between 就不要用 in 了: select id from t where num between 1 and 3
6.下面的查詢也將導(dǎo)致全表掃描:
select id from t where name like '%abc%' 若要提高效率,可以考慮全文檢索。
7.如果在 where 子句中使用參數(shù),也會(huì)導(dǎo)致全表掃描。因?yàn)镾QL只有在運(yùn)行時(shí)才會(huì)解析局部變量,但優(yōu)化程序不能將訪問(wèn)計(jì)劃的選擇推遲到運(yùn)行時(shí);它必須在編譯時(shí)進(jìn)行選擇。然而,如果在編譯時(shí)建立訪問(wèn)計(jì)劃,變量的值還是未知的,因而無(wú)法作為索引選擇的輸入項(xiàng)。如下面語(yǔ)句將進(jìn)行全表掃描:
select id from t where num=@num 可以改為強(qiáng)制查詢使用索引:
select id from t with(index(索引名))where num=@num
8.應(yīng)盡量避免在 where 子句中對(duì)字段進(jìn)行表達(dá)式操作,這將導(dǎo)致引擎放棄使用索引而進(jìn)行全表掃描。如:
select id from t where num/2=100 應(yīng)改為:
select id from t where num=100*2
9.應(yīng)盡量避免在where子句中對(duì)字段進(jìn)行函數(shù)操作,這將導(dǎo)致引擎放棄使用索引而進(jìn)行全表掃描。如:
select id from t where substring(name,1,3)='abc'--name以abc開頭的id select id from t where datediff(day,createdate,'2005-11-30')=0--?2005-11-30?生成的id 應(yīng)改為:
select id from t where name like 'abc%'
select id from t where createdate>='2005-11-30' and createdate<'2005-12-1'
10.不要在 where 子句中的“=”左邊進(jìn)行函數(shù)、算術(shù)運(yùn)算或其他表達(dá)式運(yùn)算,否則系統(tǒng)將可能無(wú)法正確使用索引。
11.在使用索引字段作為條件時(shí),如果該索引是復(fù)合索引,那么必須使用到該索引中的第一個(gè)字段作為條件時(shí)才能保證系統(tǒng)使用該索引,否則該索引將不會(huì)被使用,并且應(yīng)盡可能的讓字段順序與索引順序相一致。
12.不要寫一些沒(méi)有意義的查詢,如需要生成一個(gè)空表結(jié)構(gòu):
select col1,col2 into #t from t where 1=0
這類代碼不會(huì)返回任何結(jié)果集,但是會(huì)消耗系統(tǒng)資源的,應(yīng)改成這樣:
create table #t(...)13.很多時(shí)候用 exists 代替 in 是一個(gè)好的選擇:
select num from a where num in(select num from b)用下面的語(yǔ)句替換:
select num from a where exists(select 1 from b where num=a.num)
14.并不是所有索引對(duì)查詢都有效,SQL 是根據(jù)表中數(shù)據(jù)來(lái)進(jìn)行查詢優(yōu)化的,當(dāng)索引列有大量數(shù)據(jù)重復(fù)時(shí),SQL查詢可能不會(huì)去利用索引,如一表中有字段 sex,male、female 幾乎各一半,那么即使在sex上建了索引也對(duì)查詢效率起不了作用。
15.索引并不是越多越好,索引固然可以提高相應(yīng)的 select 的效率,但同時(shí)也降低了 insert、update 及 delete 的效率,因?yàn)?insert 或 update 時(shí)有可能會(huì)重建索引,所以怎樣建索引需要慎重考慮,視具體情況而定。一個(gè)表的索引數(shù)最好不要超過(guò)6個(gè),若太多則應(yīng)考慮一些不常使用到的列上建的索引是否有必要。
16.應(yīng)盡可能的避免更新 clustered 索引數(shù)據(jù)列,因?yàn)?clustered 索引數(shù)據(jù)列的順序就是表記錄的物理存儲(chǔ)順序,一旦該列值改變將導(dǎo)致整個(gè)表記錄的順序的調(diào)整,會(huì)耗費(fèi)相當(dāng)大的資源。若應(yīng)用系統(tǒng)需要頻繁更新 clustered 索引數(shù)據(jù)列,那么需要考慮是否應(yīng)將該索引建為 clustered 索引。
17.盡量使用數(shù)字型字段,若只含數(shù)值信息的字段盡量不要設(shè)計(jì)為字符型,這會(huì)降低查詢和連接的性能,并會(huì)增加存儲(chǔ)開銷。這是因?yàn)橐嬖谔幚聿樵兒瓦B接時(shí)會(huì)逐個(gè)比較字符串中每一個(gè)字符,而對(duì)于數(shù)字型而言只需要比較一次就夠了。
18.盡可能的使用 varchar/nvarchar 代替 char/nchar,因?yàn)槭紫茸冮L(zhǎng)字段存儲(chǔ)空間小,可以節(jié)省存儲(chǔ)空間(定長(zhǎng)字段即使在數(shù)據(jù)為null時(shí)也需要定長(zhǎng)的存儲(chǔ)空間(7.0及更高版本)),其次對(duì)于查詢來(lái)說(shuō),在一個(gè)相對(duì)較小的字段內(nèi)搜索效率顯然要高些,而且每頁(yè)(8KB)可能存儲(chǔ)更多的記錄數(shù),這樣也可以減少I/O的消耗而提高性能。
19.任何地方都不要使用 select * from t,用具體的字段列表代替“*”,不要返回用不到的任何字段。
20.盡量使用表變量來(lái)代替臨時(shí)表。如果表變量包含大量數(shù)據(jù),請(qǐng)注意索引非常有限(只有主鍵索引)。
21.避免頻繁創(chuàng)建和刪除臨時(shí)表,以減少系統(tǒng)表資源的消耗。
22.臨時(shí)表并不是不可使用,適當(dāng)?shù)厥褂盟鼈兛梢允鼓承├谈行?,例如,?dāng)需要重復(fù)引用大型表或常用表中的某個(gè)數(shù)據(jù)集時(shí)。但是,對(duì)于一次性事件,最好使用導(dǎo)出表。
23.在新建臨時(shí)表時(shí),如果一次性插入數(shù)據(jù)量很大,那么可以使用 select into 代替 create table,避免造成大量 log,以提高速度;如果數(shù)據(jù)量不大,為了緩和系統(tǒng)表的資源,應(yīng)先 create table,然后 insert。
24.如果使用到了臨時(shí)表,在存儲(chǔ)過(guò)程的最后務(wù)必將所有的臨時(shí)表顯式刪除,先 truncate table,然后 drop table,這樣可以避免系統(tǒng)表的較長(zhǎng)時(shí)間鎖定。
25.盡量避免使用游標(biāo),因?yàn)橛螛?biāo)的效率較差,如果游標(biāo)操作的數(shù)據(jù)超過(guò)1萬(wàn)行,那么就應(yīng)該考慮改寫。
1.應(yīng)盡量避免在 where 子句中對(duì)字段進(jìn)行 null 值判斷,否則將導(dǎo)致引擎放棄使用索引而進(jìn)行全表掃描,如: select id from t where num is null 可以在num上設(shè)置默認(rèn)值0,確保表中num列沒(méi)有null值,然后這樣查詢:
select id from t where num=0 2.應(yīng)盡量避免在 where 子句中使用!=或<>操作符,否則將引擎放棄使用索引而進(jìn)行全表掃描。優(yōu)化器將無(wú)法通過(guò)索引來(lái)確定將要命中的行數(shù),因此需要搜索該表的所有行。
3.應(yīng)盡量避免在 where 子句中使用 or 來(lái)連接條件,否則將導(dǎo)致引擎放棄使用索引而進(jìn)行全表掃描,如:
select id from t where num=10 or num=20 可以這樣查詢:
select id from t where num=10 union all select id from t where num=20 4.in 和 not in 也要慎用,因?yàn)镮N會(huì)使系統(tǒng)無(wú)法使用索引,而只能直接搜索表中的數(shù)據(jù)。如:
select id from t where num in(1,2,3)對(duì)于連續(xù)的數(shù)值,能用 between 就不要用 in 了: select id from t where num between 1 and 3 5.盡量避免在索引過(guò)的字符數(shù)據(jù)中,使用非打頭字母搜索。這也使得引擎無(wú)法利用索引。見(jiàn)如下例子:
SELECT * FROM T1 WHERE NAME LIKE ?%L%‘ SELECT * FROM T1 WHERE SUBSTING(NAME,2,1)=‘L‘ SELECT * FROM T1 WHERE NAME LIKE ?L%‘
即使NAME字段建有索引,前兩個(gè)查詢依然無(wú)法利用索引完成加快操作,引擎不得不對(duì)全表所有數(shù)據(jù)逐條操作來(lái)完成任務(wù)。而第三個(gè)查詢能夠使用索引來(lái)加快操作。
6.必要時(shí)強(qiáng)制查詢優(yōu)化器使用某個(gè)索引,如在 where 子句中使用參數(shù),也會(huì)導(dǎo)致全表掃描。因?yàn)镾QL只有在運(yùn)行時(shí)才會(huì)解析局部變量,但優(yōu)化程序不能將訪問(wèn)計(jì)劃的選擇推遲到運(yùn)行時(shí);它必須在編譯時(shí)進(jìn)行選擇。然而,如果在編譯時(shí)建立訪問(wèn)計(jì)劃,變量的值還是未知的,因而無(wú)法作為索引選擇的輸入項(xiàng)。如下面語(yǔ)句將進(jìn)行全表掃描: select id from t where num=@num 可以改為強(qiáng)制查詢使用索引:
select id from t with(index(索引名))where num=@num 7.應(yīng)盡量避免在 where 子句中對(duì)字段進(jìn)行表達(dá)式操作,這將導(dǎo)致引擎放棄使用索引而進(jìn)行全表掃描。如: SELECT * FROM T1 WHERE F1/2=100 應(yīng)改為: SELECT * FROM T1 WHERE F1=100*2 SELECT * FROM RECORD WHERE SUBSTRING(CARD_NO,1,4)=‘5378‘ 應(yīng)改為: SELECT * FROM RECORD WHERE CARD_NO LIKE ?5378%‘ SELECT member_number, first_name, last_name FROM members WHERE DATEDIFF(yy,datofbirth,GETDATE())> 21 應(yīng)改為: SELECT member_number, first_name, last_name FROM members WHERE dateofbirth < DATEADD(yy,-21,GETDATE())即:任何對(duì)列的操作都將導(dǎo)致表掃描,它包括數(shù)據(jù)庫(kù)函數(shù)、計(jì)算表達(dá)式等等,查詢時(shí)要盡可能將操作移至等號(hào)右邊。
8.應(yīng)盡量避免在where子句中對(duì)字段進(jìn)行函數(shù)操作,這將導(dǎo)致引擎放棄使用索引而進(jìn)行全表掃描。如: select id from t where substring(name,1,3)=‘a(chǎn)bc‘–name以abc開頭的id select id from t where datediff(day,createdate,‘2005-11-30′)=0–?2005-11-30‘生成的id 應(yīng)改為: select id from t where name like ?abc%‘ select id from t where createdate>=‘2005-11-30′ and createdate<‘2005-12-1′
9.不要在 where 子句中的―=‖左邊進(jìn)行函數(shù)、算術(shù)運(yùn)算或其他表達(dá)式運(yùn)算,否則系統(tǒng)將可能無(wú)法正確使用索引。
10.在使用索引字段作為條件時(shí),如果該索引是復(fù)合索引,那么必須使用到該索引中的第一個(gè)字段作為條件時(shí)才能保證系統(tǒng)使用該索引,否則該索引將不會(huì)被使用,并且應(yīng)盡可能的讓字段順序與索引順序相一致。
11.很多時(shí)候用 exists是一個(gè)好的選擇: select num from a where num in(select num from b)用下面的語(yǔ)句替換: select num from a where exists(select 1 from b where num=a.num)SELECT SUM(T1.C1)FROM T1 WHERE((SELECT COUNT(*)FROM T2 WHERE T2.C2=T1.C2>0)SELECT SUM(T1.C1)FROM T1WHERE EXISTS(SELECT * FROM T2 WHERE T2.C2=T1.C2)兩者產(chǎn)生相同的結(jié)果,但是后者的效率顯然要高于前者。因?yàn)楹笳卟粫?huì)產(chǎn)生大量鎖定的表掃描或是索引掃描。
如果你想校驗(yàn)表里是否存在某條紀(jì)錄,不要用count(*)那樣效率很低,而且浪費(fèi)服務(wù)器資源。可以用EXISTS代替。如: IF(SELECT COUNT(*)FROM table_name WHERE column_name = ?xxx‘)可以寫成:
IF EXISTS(SELECT * FROM table_name WHERE column_name = ?xxx‘)
經(jīng)常需要寫一個(gè)T_SQL語(yǔ)句比較一個(gè)父結(jié)果集和子結(jié)果集,從而找到是否存在在父結(jié)果集中有而在子結(jié)果集中沒(méi)有的記錄,如: SELECT a.hdr_key FROM hdr_tbl a—-tbl a 表示tbl用別名a代替
WHERE NOT EXISTS(SELECT * FROM dtl_tbl b WHERE a.hdr_key = b.hdr_key)SELECT a.hdr_key FROM hdr_tbl a LEFT JOIN dtl_tbl b ON a.hdr_key = b.hdr_key WHERE b.hdr_key IS NULL SELECT hdr_key FROM hdr_tbl WHERE hdr_key NOT IN(SELECT hdr_key FROM dtl_tbl)三種寫法都可以得到同樣正確的結(jié)果,但是效率依次降低。12.盡量使用表變量來(lái)代替臨時(shí)表。如果表變量包含大量數(shù)據(jù),請(qǐng)注意索引非常有限(只有主鍵索引)。
13.避免頻繁創(chuàng)建和刪除臨時(shí)表,以減少系統(tǒng)表資源的消耗。14.臨時(shí)表并不是不可使用,適當(dāng)?shù)厥褂盟鼈兛梢允鼓承├谈行?,例如,?dāng)需要重復(fù)引用大型表或常用表中的某個(gè)數(shù)據(jù)集時(shí)。但是,對(duì)于一次性事件,最好使用導(dǎo)出表。
15.在新建臨時(shí)表時(shí),如果一次性插入數(shù)據(jù)量很大,那么可以使用 select into 代替 create table,避免造成大量 log,以提高速度;如果數(shù)據(jù)量不大,為了緩和系統(tǒng)表的資源,應(yīng)先create table,然后insert。
16.如果使用到了臨時(shí)表,在存儲(chǔ)過(guò)程的最后務(wù)必將所有的臨時(shí)表顯式刪除,先 truncate table,然后 drop table,這樣可以避免系統(tǒng)表的較長(zhǎng)時(shí)間鎖定。
17.在所有的存儲(chǔ)過(guò)程和觸發(fā)器的開始處設(shè)置 SET NOCOUNT ON,在結(jié)束時(shí)設(shè)置 SET NOCOUNT OFF。無(wú)需在執(zhí)行存儲(chǔ)過(guò)程和觸發(fā)器的每個(gè)語(yǔ)句后向客戶端發(fā)送 DONE_IN_PROC 消息。18.盡量避免大事務(wù)操作,提高系統(tǒng)并發(fā)能力。19.盡量避免向客戶端返回大數(shù)據(jù)量,若數(shù)據(jù)量過(guò)大,應(yīng)該考慮相應(yīng)需求是否合理。
20.避免使用不兼容的數(shù)據(jù)類型。例如float和int、char和varchar、binary和varbinary是不兼容的。數(shù)據(jù)類型的不兼容可能使優(yōu)化器無(wú)法執(zhí)行一些本來(lái)可以進(jìn)行的優(yōu)化操作。例如: SELECT name FROM employee WHERE salary > 60000 在這條語(yǔ)句中,如salary字段是money型的,則優(yōu)化器很難對(duì)其進(jìn)行優(yōu)化,因?yàn)?0000是個(gè)整型數(shù)。我們應(yīng)當(dāng)在編程時(shí)將整型轉(zhuǎn)化成為錢幣型,而不要等到運(yùn)行時(shí)轉(zhuǎn)化。
21.充分利用連接條件,在某種情況下,兩個(gè)表之間可能不只一個(gè)的連接條件,這時(shí)在 WHERE 子句中將連接條件完整的寫上,有可能大大提高查詢速度。例:
SELECT SUM(A.AMOUNT)FROM ACCOUNT A,CARD B WHERE A.CARD_NO = B.CARD_NO SELECT SUM(A.AMOUNT)FROM ACCOUNT A,CARD B WHERE A.CARD_NO = B.CARD_NO AND A.ACCOUNT_NO=B.ACCOUNT_NO 第二句將比第一句執(zhí)行快得多。
22、使用視圖加速查詢
把表的一個(gè)子集進(jìn)行排序并創(chuàng)建視圖,有時(shí)能加速查詢。它有助于避免多重排序 操作,而且在其他方面還能簡(jiǎn)化優(yōu)化器的工作。例如: SELECT cust.name,rcvbles.balance,……other columns FROM cust,rcvbles WHERE cust.customer_id = rcvlbes.customer_id AND rcvblls.balance>0 AND cust.postcode>―98000‖ ORDER BY cust.name 如果這個(gè)查詢要被執(zhí)行多次而不止一次,可以把所有未付款的客戶找出來(lái)放在一個(gè)視圖中,并按客戶的名字進(jìn)行排序: CREATE VIEW DBO.V_CUST_RCVLBES AS SELECT cust.name,rcvbles.balance,……other columns FROM cust,rcvbles WHERE cust.customer_id = rcvlbes.customer_id AND rcvblls.balance>0 ORDER BY cust.name 然后以下面的方式在視圖中查詢: SELECT * FROM V_CUST_RCVLBES WHERE postcode>―98000‖
視圖中的行要比主表中的行少,而且物理順序就是所要求的順序,減少了磁盤I/O,所以查詢工作量可以得到大幅減少。
23、能用DISTINCT的就不用GROUP BY SELECT OrderID FROM Details WHERE UnitPrice > 10 GROUP BY OrderID 可改為:
SELECT DISTINCT OrderID FROM Details WHERE UnitPrice > 10 24.能用UNION ALL就不要用UNION UNION ALL不執(zhí)行SELECT DISTINCT函數(shù),這樣就會(huì)減少很多不必要的資源
35.盡量不要用SELECT INTO語(yǔ)句。
SELECT INOT 語(yǔ)句會(huì)導(dǎo)致表鎖定,阻止其他用戶訪問(wèn)該表。上面我們提到的是一些基本的提高查詢速度的注意事項(xiàng),但是在更多的情況下,往往需要反復(fù)試驗(yàn)比較不同的語(yǔ)句以得到最佳方案。最好的方法當(dāng)然是測(cè)試,看實(shí)現(xiàn)相同功能的SQL語(yǔ)句哪個(gè)執(zhí)行時(shí)間最少,但是數(shù)據(jù)庫(kù)中如果數(shù)據(jù)量很少,是比較不出來(lái)的,這時(shí)可以用查看執(zhí)行計(jì)劃,即:把實(shí)現(xiàn)相同功能的多條SQL語(yǔ)句考到查詢分析器,按CTRL+L看查所利用的索引,表掃描次數(shù)(這兩個(gè)對(duì)性能影響最大),總體上看詢成本百分比即可。
第二篇:SQL語(yǔ)句性能優(yōu)化
我也做了很長(zhǎng)時(shí)間醫(yī)療軟件,也寫過(guò)不少sql優(yōu)化,沒(méi)有詳細(xì)記錄下來(lái),個(gè)人感覺(jué)下面轉(zhuǎn)載的更符合醫(yī)院醫(yī)療軟件實(shí)際業(yè)務(wù),很認(rèn)可大部分所寫的原則,固轉(zhuǎn)載過(guò)來(lái),以作借鑒。軟件的根本還是在于更細(xì)更精,在于從客戶的實(shí)際使用考慮問(wèn)題。
性能優(yōu)化原則1:永遠(yuǎn)避免困境
利用緩存把字典數(shù)據(jù)取到中間服務(wù)器或是客戶端替代直接sql查詢,如,門診醫(yī)生站把字典下載到客戶端,減少執(zhí)行次數(shù)。
一次性取數(shù)據(jù)到客戶端,然后再逐條處理,而不是分次取數(shù)據(jù),處理好一條數(shù)據(jù)再取下一條再處理。例:門診收費(fèi)取hjcfmxk例子,原來(lái)是一張?zhí)幏綏l明細(xì)都查詢一次,查詢后再處理,現(xiàn)改為一次把所有明細(xì)都取過(guò)來(lái),然后一條條處理
盡量減少光標(biāo),看能不能用臨時(shí)表
性能優(yōu)化原則2:kiss原則
對(duì)于where 條件中的左邊可以利用索引的字段Keep it simple stupid,左邊盡量避免用函數(shù)(substring,isnull,upper,lower),參加計(jì)算+,-*/
例子1:select * from ZY_BRFYMXK where substring(zxrq,1,8)='20081212‘
select * from ZY_BRFYMXK where zxrq between '2008121200' and '2008121224' 例子2:
select * from zy_detail_charge where SUBSTRING(patient_id,1,10)=
substring('000005090600',1,10)這句耗時(shí)30秒以上
select * from zy_detail_charge where patient_id like substring('000005090600',1,10)+'%' 這句耗時(shí)2秒以內(nèi)
性能優(yōu)化原則3:盡可能利用到索引
例:select * from ZY_BRFYMXK a(nolock),VW_LSYZK b(nolock)where a.syxh=3 and a.yzxh=b.xh and a.fylb=0
select * from ZY_BRFYMXK a(nolock),VW_LSYZK b(nolock)where a.syxh=3 and a.yzxh=b.xh and a.fylb=0 and b.syxh=3
性能優(yōu)化原則4:or,避而遠(yuǎn)之
對(duì)于索引字段盡力避免用or,普通字段可以用or,解決要么分解成多個(gè)sql,要么用業(yè)務(wù)規(guī)則避免,例:declare @rq1 ut_rq16,@syxh ut_syxh
select @rq1='20081201'
select @syxh=157
性能優(yōu)化原則5:避免大批量數(shù)據(jù)取到前臺(tái)
例: select * from ZY_BRSYK cyrq between ‘20080901’ and ‘20081201‘,對(duì)于大醫(yī)院每天100多人,90天是9000條數(shù)據(jù)
性能優(yōu)化原則6:事務(wù),盡可能的短吧
所有計(jì)算、對(duì)臨時(shí)表的更新都應(yīng)但放在事務(wù)外,事務(wù)中最好只有更新和插入正式表操作.因?yàn)槭聞?wù)中產(chǎn)生的鎖只有在commit tran是才會(huì)釋放。
性能優(yōu)化原則7:熱表,留在最后吧
熱表是頻繁調(diào)用的表。如:sf_mzcfk,zy_brfymxk,bq_fyqqk.對(duì)于熱表盡量放在事務(wù)最后:這樣鎖的時(shí)間短。大家都堅(jiān)持這樣,死鎖的可能性就小。如果都是熱表各個(gè)存儲(chǔ)過(guò)程更新表的順序應(yīng)當(dāng)一樣這樣可以避免死鎖
性能優(yōu)化原則8:創(chuàng)建臨時(shí)表一定要避免在事務(wù)中作
如create #tempXX(…)
Select * into #tempXX from …
因?yàn)閯?chuàng)建臨時(shí)表會(huì)鎖tempdb的系統(tǒng)表
例:生成#temp1放在事務(wù)內(nèi)外,用sp_lock2 ‘’觀察結(jié)果
if object_id('tempdb..#temp1','U')is not null
drop table #temp1
begin tran
select * into #temp1 from ZY_BRSYK where ryrq>'20080901‘
select * from #temp1
waitfor delay '00:00:10'
commit
性能優(yōu)化原則9:大的報(bào)表查詢避免與正常業(yè)務(wù)碰撞
如果沒(méi)有查詢服務(wù)器,那要在存儲(chǔ)過(guò)程中限制不能操作加上如:
declare @rq1 ut_rq16,@rq2 ut_rq16,@now ut_rq16
select @rq1=convert(varchar(8),getdate(),112)+'08:00:00'
select @rq1=convert(varchar(8),getdate(),112)+'11:30:00'
select @now=convert(char(8),getdate(),112)+convert(char(8),getdate(),8)
if @now>@rq1 and @now<@rq2
begin
select '上午繁忙時(shí)間段不能作此查詢'
return
end
性能優(yōu)化原則10:存儲(chǔ)過(guò)程避免大的if…else…
這個(gè)常出項(xiàng)在業(yè)務(wù)相同表不同的存儲(chǔ)過(guò)程中,因?yàn)檫@樣常到if …else …原來(lái)醫(yī)技接口中很多這種存儲(chǔ)過(guò)程,當(dāng)時(shí)把門診住院業(yè)務(wù)放在一個(gè)存儲(chǔ)過(guò)程中。這樣最大的問(wèn)題是sql server會(huì)根據(jù)sql語(yǔ)句來(lái)compile存儲(chǔ),這個(gè)過(guò)程會(huì)生成優(yōu)化計(jì)劃,決定用那個(gè)索引。如果存儲(chǔ)過(guò)程用到門診表compile一下,到用到住院表是發(fā)現(xiàn)不對(duì),又會(huì)compile一下,這樣不停compile.compile很號(hào)時(shí)間要1-2秒,而且一個(gè)存儲(chǔ)過(guò)成在compile是,所有調(diào)用這個(gè)存儲(chǔ)過(guò)程的進(jìn)程都要在排隊(duì)等候,因?yàn)樗麜?huì)獨(dú)占鎖這個(gè)存儲(chǔ)過(guò)程
例:usp_yjjk_getwzxxm_old.sql,后改為:
usp_yjjk_getwzxxm.sql, usp_yjjk_getwzxxm_mz.sql,usp_yjjk_getwzxxm_zy.sql
性能優(yōu)化原則11:進(jìn)攻是最好的防守
在普通編程語(yǔ)句對(duì)于數(shù)據(jù)校驗(yàn)總是用防守辦法先判斷,后再作相應(yīng)處理。而在sql中先處理再判斷性能會(huì)好很多。
--更新藥品庫(kù)存。
If exists(select 1 from YK_YKZKC WHERE idm=100 and kcsl>50)
begin
update YK_YKZKC set kcsl=kcsl-50 where idm=100
End
Else begin
rollback tran
Select ‘F庫(kù)存不夠’
return
end
--改為
update YK_YKZKC set kcsl=kcsl-50 where idm=100 and kcsl>50
If @@rowcount<=0
Begin
Rollbakc tran
Select ‘F庫(kù)存不夠’
end
--取未執(zhí)行的醫(yī)技項(xiàng)目,日表沒(méi)有數(shù)據(jù)就到年表中查找
if exists(select a.* from SF_MZCFK a(nolock),SF_CFMXK b(nolock)
begin
select a.* into #temp1 from SF_MZCFK a(nolock),SF_CFMXK b(nolock)
end
else begin
select a.* into #temp1 from SF_NMZCFK a(nolock),SF_NCFMXK b(nolock)
end
--改為
Insert into #temp1 select a.*
from SF_MZCFK a(nolock),SF_CFMXK b(nolock)
If @@rowcount=0
Begin
Insert into #temp1 select a.*
from SF_NMZCFK a(nolock),SF_NCFMXK b(nolock)
end
性能優(yōu)化原則12:trig最后的手段
Trig(觸發(fā)器)的處理的處理機(jī)制是滿足條件時(shí)就會(huì)在源語(yǔ)句后面加上trig中的代碼進(jìn)行執(zhí)行。
它有兩個(gè)致命的弊端:(1)不清楚有trig的人會(huì)對(duì)于執(zhí)行結(jié)果感到迷惑。如常有在插入一張表如果主鍵是indentity的值常取用select @@identity。但如是有trig,tring中有表插入操作,這時(shí)的@@identity可能就不是想要的值。(2)trig會(huì)束縛選擇。如:有一套單據(jù)主表和明細(xì)表,當(dāng)明細(xì)表的金額更新時(shí),要同步主表的金額,當(dāng)程序是一條條更新明細(xì)時(shí)用trig的作法是每當(dāng)更新一條明細(xì)記錄時(shí)都算一處所有明細(xì)表的總金額,再去更新主表的金額。這樣有多少條明細(xì)就要算多少次,好的作法是不要trig,直接在sql語(yǔ)句中明細(xì)更新完明后,一次性算出總金額每條單據(jù)的總金額,再更新主表的金額。
對(duì)于trig如果有其他手段就一定要避免用trig.性能優(yōu)化原則13:用戶說(shuō)好才是真的好
1)有時(shí)sql語(yǔ)句性能難以優(yōu)化,但用戶對(duì)于系統(tǒng)響應(yīng)速度還是不滿意。這時(shí)可以從業(yè)務(wù)分析處理。
如:我們退費(fèi)模塊錄入發(fā)票號(hào)原來(lái)是用fph like ‘XXX%’。用戶報(bào)怨慢,后來(lái)改為先用fph=‘XXX’來(lái)查,如查不到再fph like ‘XXX%’。這樣在絕大部情況下速度都非???,同時(shí)也滿足小部分情況下模糊查詢的需求。
如:我們的程序要查日表和年表。如果通過(guò)日表union表視圖去查會(huì)非常慢,性能也難以優(yōu)化。程序改為普通情況下不查年表,用戶勾上年表標(biāo)志時(shí)才查年表。
(2)查詢統(tǒng)計(jì)很多數(shù)據(jù)時(shí)間比較長(zhǎng),就以查詢完一部分?jǐn)?shù)據(jù)后可以顯示這部分?jǐn)?shù)據(jù)或是用提示,這樣用戶清楚系統(tǒng)在作事情也知道大概進(jìn)度。這樣情緒上會(huì)好很多。
(3)查詢模塊常有一進(jìn)入時(shí)也默認(rèn)一個(gè)查詢,如果性能好,查詢又合用戶心意,這種設(shè)計(jì)非常好,如果性能不好,那就不是好的設(shè)計(jì)。用戶對(duì)于進(jìn)入都困難的模塊是沒(méi)有好感的。
(4)有戶的耐心與查詢出的記錄成正比。用戶痛恨等待很久卻沒(méi)有查詢出記錄。
對(duì)于非常慢的查詢,如果有些子查詢非??炜梢韵茸鬟@樣查詢以避免查詢很久卻沒(méi)有數(shù)據(jù)出來(lái)的情況。如:按病歷號(hào)查在院病人所有費(fèi)有明細(xì),可以先查一下這個(gè)病歷是不是有對(duì)應(yīng)病人。
實(shí)戰(zhàn)技巧1:用exists、in代替distinct
Distinct實(shí)際上是先收集再刪除這樣兩步都耗資源。
Exists,in會(huì)隱式過(guò)濾掉重復(fù)的記錄
例查自2009年以來(lái)有金額大于100的藥品的病人
select distinct a.blh,a.hzxm from ZY_BRXXK a(nolock),ZY_BRSYK b(nolock),ZY_BRFYMXK c(nolock)where a.patid=b.patid and b.syxh=c.syxh and c.zxrq>'2009' and c.zje>100--改為
select a.blh,a.hzxm from ZY_BRXXK a where exists(select 1 from ZY_BRSYK
b(nolock),ZY_BRFYMXK c(nolock)where a.patid=b.patid and b.syxh=c.syxh and
c.zxrq>'2009'and c.zje>100)
實(shí)戰(zhàn)技巧2:縮短union
select …from A,B,C,D,E1
where(E1的條件)
and(其他表聯(lián)接條件)
union
select …from A,B,C,D,E2
where(E2的條件)
and(其他表接接條件)
改為
select …from A,B,C,D,(select...from E1where(E1條件)
union
select …from E2where(E2條件))E where(其他條件)
當(dāng)涉及ABCD表部分耗資源而E1,E2不耗資源時(shí)是這樣,如果反過(guò)來(lái)則改后的性能不一定好。查2009年4月后入院的在院病人在2905病區(qū)發(fā)生的所有費(fèi)用明細(xì)
select a.hzxm,b.cyrq,d.ypmc,d.ypgg,c.ypsl/c.dwxs ypsl, c.ypdw
select a.hzxm,b.cyrq,d.ypmc,d.ypgg,c.ypsl/c.dwxs ypsl, c.ypdw
from ZY_BRXXK a(nolock),ZY_BRSYK b(nolock),ZY_BRFYMXK c(nolock),YK_YPCDMLK d where a.patid=b.patid and b.ryrq>'200904' and b.brzt not in(3,8,9)and b.syxh=c.syxh and c.bqdm='2905' and c.idm=d.idm
union all
select a.hzxm,b.cyrq,d.name,d.xmgg,c.ypsl/c.dwxs ypsl, c.ypdw
from ZY_BRXXK a(nolock),ZY_BRSYK b(nolock),ZY_BRFYMXK c(nolock),YY_SFXXMK d where a.patid=b.patid and b.ryrq>'200904' and b.brzt not in(3,8,9)and b.syxh=c.syxh and c.bqdm='2905' and c.ypdm=d.id and c.idm=0
--改為
select a.hzxm,b.cyrq,d.ypmc,d.ypgg,c.ypsl/c.dwxs ypsl, c.ypdw
from ZY_BRXXK a(nolock),ZY_BRSYK b(nolock),ZY_BRFYMXK c(nolock),(select ypmc,ypgg,ypdm,idm idm from YK_YPCDMLK union select name,xmgg,id,0 from YY_SFXXMK)d
where a.patid=b.patid and b.ryrq>'200904' and b.brzt not in(3,8,9)and b.syxh=c.syxh and c.bqdm='2905' and c.idm=d.idm and c.ypdm=d.ypdm
實(shí)戰(zhàn)技巧3:合并sql
把表和where條件類似的兩個(gè)或是多個(gè)sql合并為一個(gè)sql.--查2009年以后的普通、急診、專家掛號(hào)人數(shù)
declare @ptghs int,@jzghs int,@zjghs int
select @ptghs=0,@jzghs=0,@zjghs=0
select @ptghs=count(*)from GH_GHZDK where ghrq>'2009' and ghlb=0
select @jzghs=count(*)from GH_GHZDK where ghrq>'2009' and ghlb=1
select @zjghs=count(*)from GH_GHZDK where ghrq>'2009' and ghlb=2
select @ptghs,@jzghs,@zjghs
--改為
select @ptghs=0,@jzghs=0,@zjghs=0
select @ptghs=sum(case when ghlb=0 then 1 else 0 end),@jzghs=sum(case when ghlb=1 then 1 else 0 end), @zjghs=sum(case when ghlb=2 then 1 else 0 end)
from GH_GHZDK where ghrq>'2009'
select @ptghs,@jzghs,@zjghs
實(shí)戰(zhàn)技巧4:去掉游標(biāo)
把游標(biāo)當(dāng)作編程語(yǔ)言的for,do---while的方式,很多情況下都可以去掉,如果光標(biāo)中間sql語(yǔ)句只有一條一般都是可以去掉光標(biāo)改為一句sql。
--查當(dāng)天出院出院日期在2009年4月1到9日間病人的zfdj,zfje置為0
declare @syxh ut_syxh
declare cur1 cursor for select syxh from ZY_BRSYK where cyrq>='20090401' and cyrq<'20090410'
open cur1
fetch cur1 into @syxh
while @@fetch_status=0
begin
fetch cur1 into @syxh
end
close cur1
deallocate cur1
--改為
update ZY_BRFYMXK set zfdj=0,zfje=0
from ZY_BRFYMXK a,ZY_BRSYK b
where a.syxh=b.syxh and b.cyrq>='20090401' and b.cyrq<'20090410'
實(shí)戰(zhàn)技巧5:取代count
利用內(nèi)部函數(shù)代替
declare @count int
select * into #tmep1 from ZY_BRFYMXK WHERE zxrq>'200901'
select @count=@@rowcount—可以得到count值
select @count
select @count=count(*)from #tmep1—可以被取代
select @count
利用exists而不count判斷有沒(méi)有記錄
declare @count int
Select @count=count(1)from ZY_BRFYMXK WHERE zxrq>'2009‘
If @count>0 … else ….--改為
If exists(Select 1 from ZY_BRFYMXK WHERE zxrq>'2009’)… else ….
第三篇:Web前端頁(yè)面性能優(yōu)化小結(jié)
Web前端頁(yè)面性能優(yōu)化小結(jié)
Web前端頁(yè)面性能優(yōu)化小結(jié)
影響用戶訪問(wèn)的最大部分是前端的頁(yè)面。網(wǎng)站的劃分一般為二:前端和后臺(tái)。我們可以理解成后臺(tái)是用來(lái)實(shí)現(xiàn)網(wǎng)站的功能的,比如:實(shí)現(xiàn)用戶注冊(cè),用戶能夠?yàn)槲恼掳l(fā)表評(píng)論等等。而前端呢?其實(shí)應(yīng)該是屬于功能的表現(xiàn)。
而我們建設(shè)網(wǎng)站的目的是什么呢?不就是為了讓目標(biāo)人群來(lái)訪問(wèn)嗎?所以我們可以理解成前端才是真正和用戶接觸的。
除了后臺(tái)需要在性能上做優(yōu)化外,其實(shí)前端的頁(yè)面更需要在性能優(yōu)化上下功夫,只有這樣才能給我們的用戶帶來(lái)更好的用戶體驗(yàn)。不僅僅如此,如果前端優(yōu)化得好,他不僅可以為企業(yè)節(jié)約成本,他還能給用戶帶來(lái)更多的用戶,因?yàn)樵鰪?qiáng)的用戶體驗(yàn)。說(shuō)了這么多,那么我們應(yīng)該如何對(duì)我們前端的頁(yè)面進(jìn)行性能優(yōu)化呢?
前端的頁(yè)面主要包括xhtml,css,js。其實(shí)xhtml就是現(xiàn)實(shí)中所談到的內(nèi)容,頁(yè)面的內(nèi)容:文字,圖片,flash,視頻等。
而前端開發(fā)工作者可以控制的是什么呢?那就是xhtml,css,js的代碼及相應(yīng)的修飾(背景)圖片。下面我就根據(jù)我自己的經(jīng)驗(yàn)來(lái)說(shuō)說(shuō):
一、提倡前端開發(fā)工程師在書寫xhtml的時(shí)候做到結(jié)構(gòu)語(yǔ)義化。結(jié)構(gòu)中主要包括了head和body兩個(gè)部分,但是我們經(jīng)常說(shuō)的是結(jié)構(gòu)語(yǔ)義化主要是body中的標(biāo)簽,但是我在這里還是簡(jiǎn)單的說(shuō)一下 head,head中其實(shí)包括了一些對(duì)于我們seo很有用的一些東西,比如
title,description,keywords,這些東西在蜘蛛抓取的時(shí)候都是有幫助的,當(dāng)然,還有其他的一些,我在此就不一一說(shuō)明了,比如設(shè)置緩存等一些其他的信息。那么body中的話,包括的標(biāo)簽就很多了,我覺(jué)得作為一個(gè)合格的前端開發(fā)人員你應(yīng)該去熟悉他們,比如div,span,h,ul,ol,dl,p等等這類的標(biāo)簽的使用。應(yīng)該非常合理,還有就是注意h標(biāo)簽的斷層,及h1標(biāo)簽的使用,這些都是非常重要的。同時(shí)在我們的結(jié)構(gòu)中不要出現(xiàn)style和onclick這樣的內(nèi)聯(lián)的樣式和事件.。希望大家能夠注意結(jié)構(gòu)與表現(xiàn)、行為的分離。(ps:標(biāo)簽語(yǔ)義化的好處:1.有利于搜索引擎;2.結(jié)構(gòu)清晰的html在團(tuán)隊(duì)合作中的作用,就不必說(shuō)了吧;3.有利于盲人屏幕閱讀器。至于如何做到標(biāo)簽語(yǔ)義化,就看個(gè)人的理解了,這方面我也覺(jué)得模糊,跟個(gè)人的習(xí)慣估計(jì)也有一定的關(guān)系,總之鄒惠斌老師是認(rèn)為我的標(biāo)簽不語(yǔ)義的。)
二、css(http://zhi.ujiuye.com/web/css/),js文件數(shù)量及大小的優(yōu)化 那么關(guān)于css、js的優(yōu)化的話,一般情況下建議css和js采用外聯(lián)式。但是如果你的頁(yè)面內(nèi)容比較多,設(shè)計(jì)師把整個(gè)效果做得比較花的話,恐怕 css就非常多了,那么這種情況下,你一定要把你的css規(guī)劃好,盡量的采用縮寫,這樣可以減少css文件的大小,那么對(duì)css做相應(yīng)的規(guī)劃也可以減少 css的個(gè)數(shù),減少http請(qǐng)求數(shù),js同理。(ps:減少重復(fù)性代碼,代碼重復(fù)利用,在這里顯得特別重要)
三、背景圖片數(shù)量及大小的優(yōu)化
當(dāng)我們將設(shè)計(jì)師的設(shè)計(jì)稿還原成靜態(tài)頁(yè)面后,除非頁(yè)面所有的修飾全是色塊,內(nèi)容全是文字,沒(méi)有圖片,如果不是這樣的話,那么我們需要對(duì)圖片做優(yōu)化處理。當(dāng)然內(nèi)容圖片我們是沒(méi)有辦法了,因?yàn)樗菍儆趦?nèi)容部分的,一般情況是由于編輯處理,當(dāng)然,我在還是有一個(gè)小小的建議,如果我們的網(wǎng)站中需要有內(nèi)容圖片,希望編輯能夠?qū)⑺麄冏顑?yōu)化以后,在進(jìn)行上傳,一會(huì)兒告訴我的方法,下面我在說(shuō)說(shuō),作為前端開發(fā)應(yīng)該如何處理我們的修飾(背景)圖片。由于我們的背景圖片數(shù)量比較多,這樣的話,會(huì)給服務(wù)器帶來(lái)影響,增加了http請(qǐng)求數(shù),我們是否有一種好的解決辦法呢?這個(gè)答案是肯定的,如果你是一個(gè)合格的前端開發(fā),你應(yīng)該清楚,在我們的css定義背景的時(shí)候,可以通過(guò)坐標(biāo)來(lái)實(shí)現(xiàn)對(duì)背景進(jìn)行定位的,既然如此,那么我們可以將這些背景合并起來(lái),這樣即可減少http請(qǐng)求數(shù),同時(shí),我們?cè)诒尘罢系臅r(shí)候,也需要考慮圖片質(zhì)量,同時(shí)也需要考慮圖片的大小(ps:這里建議使用png8格式的圖片結(jié)合css sprite,同樣的圖片,png8格式會(huì)相對(duì)來(lái)比gif小)
四、內(nèi)容圖片的大小的優(yōu)化
其實(shí)剛才已經(jīng)說(shuō)了內(nèi)容圖片的問(wèn)題,那么我在這里呢,告訴大家一個(gè)比較簡(jiǎn)單的方法,就是使用雅虎提供的一個(gè)工具。他就是smushit:http:// 規(guī)范在文檔 內(nèi)加載你的樣式表。
對(duì)于擁有較大瀏覽量的首頁(yè)來(lái)說(shuō),有一種技術(shù)可以平衡內(nèi)置代碼帶來(lái)的 http 請(qǐng)求減少與通過(guò)使用外部文件進(jìn)行緩存帶來(lái)的好處。其中一個(gè)就是在首頁(yè)中內(nèi)置 javascript 和 css,但是在頁(yè)面下載完成后動(dòng)態(tài)下載外部文件,在子頁(yè)面中使用到這些文件時(shí),它們已經(jīng)緩存到瀏覽器了。
更多知識(shí)干貨分享,盡在中公優(yōu)就業(yè),>>>點(diǎn)擊進(jìn)入。
點(diǎn)擊查看>>>中公I(xiàn)T優(yōu)就業(yè)封閉式培訓(xùn),包食宿,學(xué)費(fèi)貸款,交通補(bǔ)貼,推薦就業(yè)
第四篇:6多分支結(jié)構(gòu)——select語(yǔ)句
第三節(jié)多分支結(jié)構(gòu)——select語(yǔ)句教學(xué)設(shè)計(jì)
一、教學(xué)目標(biāo)
1、知識(shí)與技能:
(1)充分理解多分支結(jié)構(gòu)的流程。
(2)能夠利用多分支結(jié)構(gòu)的思想解決實(shí)際問(wèn)題。
2、過(guò)程與方法: 培養(yǎng)學(xué)生獨(dú)立思考的能力、靈活運(yùn)用所學(xué)知識(shí)解決問(wèn)題的能力。
3、情感態(tài)度與價(jià)值觀:(1)增強(qiáng)學(xué)生思維的嚴(yán)密性。
(2)善于發(fā)現(xiàn)問(wèn)題,敢于提出疑問(wèn)并能夠針對(duì)疑問(wèn)積極主動(dòng)的思考解決。
二、教學(xué)重難點(diǎn)
1、重點(diǎn):理解多分支結(jié)構(gòu)的流程。
2、難點(diǎn):理解程序中流程的代碼描述。
三、教學(xué)過(guò)程
1、游戲引入
通過(guò)學(xué)生喜歡的心理測(cè)試的小游戲再將學(xué)生的注意力吸引到本課中來(lái)的同時(shí),讓學(xué)生初步體會(huì),選擇不同的面包能夠得到不同的測(cè)試結(jié)果。
(設(shè)計(jì)意圖:從游戲入手,滿足了學(xué)生愛(ài)玩的童心的同時(shí),集中了學(xué)生的注意了,拉近了師生之間的距離,也為后面的問(wèn)題做好鋪墊。)
2、初步理解
教師通過(guò)解密心理測(cè)試的秘密引出游戲的背后的支持者:程序代碼,帶領(lǐng)學(xué)生邊玩游戲邊看代碼,從中發(fā)現(xiàn)規(guī)律。同時(shí)提出問(wèn)題:玩游戲的過(guò)程當(dāng)中如果在文本框中輸入3,測(cè)試結(jié)果變成“你是灰太狼”,要達(dá)到這個(gè)要求需要對(duì)游戲代碼做怎樣的修改?并說(shuō)明原因
(代碼是比較抽象的概念,很難通過(guò)定義理解它,通過(guò)修改代碼從形式上讓代碼成為學(xué)生自己的東西,接觸學(xué)生看到代碼的陌生心理,同時(shí)讓學(xué)生初步體會(huì)不同的選擇對(duì)應(yīng)不同的結(jié)果。)
3、深入剖析
通過(guò)理解星貓心理測(cè)試的過(guò)程,將不同的面包對(duì)應(yīng)不同的測(cè)試結(jié)果轉(zhuǎn)化為流程圖中不同的條件對(duì)應(yīng)不同的語(yǔ)句組,通過(guò)心理測(cè)試的代碼導(dǎo)出程序基本格式。
(設(shè)計(jì)意圖:圖形是比較直觀好理解的表現(xiàn)形式,通過(guò)圖形引出結(jié)構(gòu)的流程圖,結(jié)合流程圖分析該圖是如何應(yīng)用程序語(yǔ)句描述的,以具體的程序語(yǔ)句對(duì)照理解語(yǔ)句格式的基本結(jié)構(gòu)也就不難了。)
4、模擬練習(xí)
以程序填空的形式完成分蛋游戲,進(jìn)一步體會(huì)不同的年齡段對(duì)應(yīng)不同的禮物,體驗(yàn)調(diào)試程序帶來(lái)的快樂(lè)和成就感,在這一過(guò)程中要演示學(xué)生的成果,適時(shí)給出表?yè)P(yáng)。
(設(shè)計(jì)意圖:對(duì)于初中學(xué)生來(lái)說(shuō),本節(jié)課只需要理解多分支結(jié)構(gòu)的執(zhí)行過(guò)程,理解不同的條件對(duì)應(yīng)執(zhí)行不同的語(yǔ)句組,代碼只需要簡(jiǎn)單了解。通過(guò)流程圖理解游戲在程序中的執(zhí)行過(guò)程,在通過(guò)代碼填空,加強(qiáng)對(duì)結(jié)構(gòu)的理解。)
5、深入提高
通過(guò)思考心理測(cè)試當(dāng)中沒(méi)有想選擇的面包的特殊情況的處理方法,引出當(dāng)表達(dá)式對(duì)于條件1到條件N都不符合時(shí)的處理辦法case else 語(yǔ)句組N+1.培養(yǎng)學(xué)生思考問(wèn)題的嚴(yán)密性。
(設(shè)計(jì)意圖:程序設(shè)計(jì)要求思維嚴(yán)密,考慮到所有可能出現(xiàn)的情況,通過(guò)具體的實(shí)例引領(lǐng)學(xué)生思考特殊情況并思考特殊情況的處理辦法,這樣就把抽象的問(wèn)題具體化,能夠幫助學(xué)生理解,并應(yīng)用到解決問(wèn)題的過(guò)程當(dāng)中去。)
6、小結(jié)
通過(guò)兩個(gè)游戲的流程圖以及統(tǒng)一的流程圖,進(jìn)而引出專業(yè)術(shù)語(yǔ)多分支結(jié)構(gòu)——select語(yǔ)句。
通過(guò)小結(jié),把課堂教學(xué)傳授的知識(shí)盡快化為學(xué)生的素質(zhì);使學(xué)生更深刻地理解兩個(gè)游戲的執(zhí)行流程的同時(shí)引出本課的課題,這種結(jié)構(gòu)就是VB中的多分支結(jié)構(gòu),起到畫龍點(diǎn)睛的作用。
7、知識(shí)深化
課后思考題:完成成績(jī)?cè)u(píng)價(jià)系統(tǒng),思考兩種流程圖的區(qū)別。(設(shè)計(jì)意圖:應(yīng)用所學(xué)知識(shí)解決問(wèn)題是最終目的,通過(guò)完成成績(jī)?cè)u(píng)價(jià)系統(tǒng)可以將所學(xué)知識(shí)應(yīng)用到實(shí)際問(wèn)題中去,通過(guò)思考兩種流程圖的區(qū)別能夠提高思維的嚴(yán)密性。)
四、教學(xué)反思
本節(jié)以設(shè)計(jì)四則運(yùn)算器為重點(diǎn)講了Select語(yǔ)句的基本格式。通 過(guò)上節(jié)課IF語(yǔ)句的學(xué)習(xí),學(xué)生對(duì)編程思想基本有了一定的了解,因此根據(jù)本節(jié)內(nèi)容較多的特點(diǎn),在授課時(shí)除重點(diǎn)對(duì)Select語(yǔ)句格式及執(zhí)行過(guò)程詳解外,其他內(nèi)容讓學(xué)生參照教科書自己完成。并將一些課后內(nèi)容拿到課堂上來(lái),使一些接受能力強(qiáng),完成速度快的學(xué)生可以“吃得飽”。用任務(wù)驅(qū)動(dòng)和小組合作的形式,對(duì)能力稍差的同學(xué)也可以有所帶動(dòng)。通過(guò)課后幫助家長(zhǎng)設(shè)計(jì)薪金所得稅程序,使學(xué)生對(duì)納稅意識(shí)有初步了解,增強(qiáng)學(xué)生依法納稅道德意識(shí)。
第五篇:SQL語(yǔ)句 SELECT LIKE like用法詳解
SQL語(yǔ)句 SELECT LIKE like用法詳解 在SQL結(jié)構(gòu)化查詢語(yǔ)言中,LIKE語(yǔ)句有著至關(guān)重
要的作用。LIKE語(yǔ)句的語(yǔ)法格式是:select * from 表名 where 字段名 like 對(duì)
應(yīng)值(子串),它主要是針對(duì)字符型字段的,它的作用是在一個(gè)字符型字段列中檢索包含對(duì)
應(yīng)子串的。A:% 包含零個(gè)或多個(gè)字符的任意字符串:
1、LIKE'Mc%' 將搜索以字母 Mc 開
頭的所有字符串(如 McBadden)。
2、LIKE'%inger' 將搜索以字母 inger 結(jié)尾的所有字符
串(如 Ringer、Stringer)。
3、LIKE'%en%' 將搜索在任何位置包含字母 en 的所有字符串
(如 Bennet、Green、McBadden)。B:_(下劃線)任何單個(gè)字符:LIKE'_heryl' 將搜索以
字母 heryl 結(jié)尾的所有六個(gè)字母的名稱(如 Cheryl、Sheryl)。C:[ ] 指定范圍([a-f])或
集合([abcdef])中的任何單個(gè)字符: 1,LIKE'[CK]ars[eo]n' 將搜索下列字符串:Carsen、Karsen、Carson 和 Karson(如 Carson)。
2、LIKE'[M-Z]inger' 將搜索以字符串 inger 結(jié)
尾、以從 M 到 Z 的任何單個(gè)字母開頭的所有名稱(如 Ringer)。D:[^] 不屬于指定范
圍([a-f])或集合([abcdef])的任何單個(gè)字符:LIKE'M[^c]%' 將搜索以字母 M 開頭,并且
第二個(gè)字母不是 c 的所有名稱(如MacFeather)。E:* 它同于DOS命令中的通配符,代
表多個(gè)字符:c*c代表cc,cBc,cbc,cabdfec等多個(gè)字符。F:?同于DOS命令中的?通配符,代表單個(gè)字符 :b?b代表brb,bFb等 G:# 大致同上,不同的是代只能代表單個(gè)數(shù)字。k#k
代表k1k,k8k,k0k。F:[!] 排除 它只代表單個(gè)字符下面我們來(lái)舉例說(shuō)明一下:例
1,查詢name字段中包含有“明”字的。select * from table1 where name like '%明%'例2,查詢name字段中以“李”字開頭。select * from table1 where name like '李*'例3,查詢name字段中含有數(shù)字的。select * from table1 where name like '%[0-9]%'例4,查詢name字段中含有小寫字母的。select * from table1 where name like '%[a-z]%'例5,查詢name字段中不含有數(shù)字的。select * from table1 where name like '%[!0-9]%'以上例子能列出什么值來(lái)顯而易見(jiàn)。但在這里,我們著重要說(shuō)明的是通配符“*”與“%”的區(qū)別。很多朋友會(huì)問(wèn),為什么我在以上查詢時(shí)有個(gè)別的表示所有字符的時(shí)候用
“%”而不用“*”?先看看下面的例子能分別出現(xiàn)什么結(jié)果:select * from table1 where
name like '*明*'select * from table1 where name like '%明%'大家會(huì)看到,前
一條語(yǔ)句列出來(lái)的是所有的記錄,而后一條記錄列出來(lái)的是name字段中含有“明”的記錄,所以說(shuō),當(dāng)我們作字符型字段包含一個(gè)子串的查詢時(shí)最好采用“%”而不用“*”,用“*”的時(shí)候只在開頭或者只在結(jié)尾時(shí),而不能兩端全由“*”代替任意字符的情況下。