真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

數(shù)據(jù)庫SQL優(yōu)化

一:優(yōu)化說明
A:有數(shù)據(jù)表明,用戶可以承受的最大等待時間為8秒。數(shù)據(jù)庫優(yōu)化策略有很多,設(shè)計初期,建立好的數(shù)據(jù)結(jié)構(gòu)對于后期性能優(yōu)化至關(guān)重要。因為數(shù)據(jù)庫結(jié)構(gòu)是系統(tǒng)的基石,基礎(chǔ)打不好,使用各種優(yōu)化策略,也不能達到很完美的效果。

成都創(chuàng)新互聯(lián)是一家專業(yè)的成都網(wǎng)站建設(shè)公司,我們專注成都網(wǎng)站設(shè)計、成都做網(wǎng)站、網(wǎng)絡(luò)營銷、企業(yè)網(wǎng)站建設(shè),友情鏈接,廣告投放平臺為企業(yè)客戶提供一站式建站解決方案,能帶給客戶新的互聯(lián)網(wǎng)理念。從網(wǎng)站結(jié)構(gòu)的規(guī)劃UI設(shè)計到用戶體驗提高,創(chuàng)新互聯(lián)力求做到盡善盡美。

B:數(shù)據(jù)庫優(yōu)化的幾個方面?
?
?可以看出來,數(shù)據(jù)結(jié)構(gòu)、SQL、索引是成本最低,且效果最好的優(yōu)化手段。

C:性能優(yōu)化是無止境的,當(dāng)性能可以滿足需求時即可,不要過度優(yōu)化。

二:優(yōu)化方向
1. SQL以及索引的優(yōu)化
首先要根據(jù)需求寫出結(jié)構(gòu)良好的SQL,然后根據(jù)SQL在表中建立有效的索引。但是如果索引太多,不但會影響寫入的效率,對查詢也有一定的影響。

2. 合理的數(shù)據(jù)庫是設(shè)計
根據(jù)數(shù)據(jù)庫三范式來進行表結(jié)構(gòu)的設(shè)計。設(shè)計表結(jié)構(gòu)時,就需要考慮如何設(shè)計才能更有效的查詢。

數(shù)據(jù)庫三范式:?
第一范式:數(shù)據(jù)表中每個字段都必須是不可拆分的最小單元,也就是確保每一列的原子性;?
第二范式:滿足一范式后,表中每一列必須有唯一性,都必須依賴于主鍵;?
第三范式:滿足二范式后,表中的每一列只與主鍵直接相關(guān)而不是間接相關(guān)(外鍵也是直接相關(guān)),字段沒有冗余。

注意:沒有最好的設(shè)計,只有最合適的設(shè)計,所以不要過分注重理論。三范式可以作為一個基本依據(jù),不要生搬硬套。

有時候可以根據(jù)場景合理地反規(guī)范化:?
A:分割表。?
B:保留冗余字段。當(dāng)兩個或多個表在查詢中經(jīng)常需要連接時,可以在其中一個表上增加若干冗余的字段,以 避免表之間的連接過于頻繁,一般在冗余列的數(shù)據(jù)不經(jīng)常變動的情況下使用。?
C:增加派生列。派生列是由表中的其它多個列的計算所得,增加派生列可以減少統(tǒng)計運算,在數(shù)據(jù)匯總時可以大大縮短運算時間。

數(shù)據(jù)庫五大約束:?
A:PRIMARY key:設(shè)置主鍵約束;?
B:UNIQUE:設(shè)置唯一性約束,不能有重復(fù)值;?
C:DEFAULT 默認值約束?
D:NOT NULL:設(shè)置非空約束,該字段不能為空;?
E:FOREIGN key :設(shè)置外鍵約束。

字段類型選擇:?
A:盡量使用TINYINT、SMALLINT、MEDIUM_INT作為整數(shù)類型而非INT,如果非負則加上UNSIGNED?
B:VARCHAR的長度只分配真正需要的空間?
C:使用枚舉或整數(shù)代替字符串類型?
D:盡量使用TIMESTAMP而非DATETIME?
E:單表不要有太多字段,建議在20以內(nèi)?
F:避免使用NULL字段,很難查詢優(yōu)化且占用額外索引空間

3. 系統(tǒng)配置的優(yōu)化
例如:MySQL數(shù)據(jù)庫my.cnf

4. 硬件優(yōu)化
更快的IO、更多的內(nèi)存。一般來說內(nèi)存越大,對于數(shù)據(jù)庫的操作越好。但是CPU多就不一定了,因為他并不會用到太多的CPU數(shù)量,有很多的查詢都是單CPU。另外使用高的IO(SSD、RAID),但是IO并不能減少數(shù)據(jù)庫鎖的機制。所以說如果查詢緩慢是因為數(shù)據(jù)庫內(nèi)部的一些鎖引起的,那么硬件優(yōu)化就沒有什么意義。

三:優(yōu)化方案
代碼優(yōu)化
之所以把代碼放到第一位,是因為這一點最容易引起技術(shù)人員的忽視。很多技術(shù)人員拿到一個性能優(yōu)化的需求以后,言必稱緩存、異步、JVM等。實際上,第一步就應(yīng)該是分析相關(guān)的代碼,找出相應(yīng)的瓶頸,再來考慮具體的優(yōu)化策略。有一些性能問題,完全是由于代碼寫的不合理,通過直接修改一下代碼就能解決問題的,比如for循環(huán)次數(shù)過多、作了很多無謂的條件判斷、相同邏輯重復(fù)多次等。

舉個例子:?
一個update操作,先查詢出entity,再執(zhí)行update,這樣無疑多了一次數(shù)據(jù)庫交互。還有一個問題,update語句可能會操作一些無需更新的字段。?
?
我們可以將表單中涉及到的屬性,以及updateTime,updateUser等賦值到entity,直接通過pdateByPrimaryKeySelective,去update特定字段。

定位慢SQL,并優(yōu)化
這是最常用、每一個技術(shù)人員都應(yīng)該掌握基本的SQL調(diào)優(yōu)手段(包括方法、工具、輔助系統(tǒng)等)。這里以MySQL為例,最常見的方式是,由自帶的慢查詢?nèi)罩净蛘唛_源的慢查詢系統(tǒng)定位到具體的出問題的SQL,然后使用explain、profile等工具來逐步調(diào)優(yōu),最后經(jīng)過測試達到效果后上線。

SqlServer執(zhí)行計劃:
通過執(zhí)行計劃,我們能得到哪些信息:?
A:哪些步驟花費的成本比較高?
B:哪些步驟產(chǎn)生的數(shù)據(jù)量多,數(shù)據(jù)量的多少用線條的粗細表示,很直觀?
C:每一步執(zhí)行了什么動作

具體優(yōu)化手段:
A:盡量少用(或者不用)sqlserver 自帶的函數(shù)?
select id from t where substring(name,1,3) = ’abc’?
select id from t where datediff(day,createdate,’2005-11-30′) = 0?
可以這樣查詢:?
select id from t where name like ‘a(chǎn)bc%’?
select id from t where createdate >= ‘2005-11-30’ and createdate < ‘2005-12-1’

B:連續(xù)數(shù)值條件,用BETWEEN不用IN:SELECT id FROM t WHERE num BETWEEN 1 AND 5?
C:Update 語句,如果只更改1、2個字段,不要Update全部字段,否則頻繁調(diào)用會引起明顯的性能消耗?
D:盡量使用數(shù)字型字段,若只含數(shù)值信息的字段盡量不要設(shè)計為字符型?
E:不建議使用 select * from t ,用具體的字段列表代替“*”,不要返回用不到的任何字段。盡量避免向客戶 端返回大數(shù)據(jù)量,若數(shù)據(jù)量過大,應(yīng)該考慮相應(yīng)需求是否合理?
F:表與表之間通過一個冗余字段來關(guān)聯(lián),要比直接使用JOIN有更好的性能?
G:select count(*) from table;這樣不帶任何條件的count會引起全表掃描?
連接池調(diào)優(yōu)?
我們的應(yīng)用為了實現(xiàn)數(shù)據(jù)庫連接的高效獲取、對數(shù)據(jù)庫連接的限流等目的,通常會采用連接池類的方案,即每一個應(yīng)用節(jié)點都管理了一個到各個數(shù)據(jù)庫的連接池。隨著業(yè)務(wù)訪問量或者數(shù)據(jù)量的增長,原有的連接池參數(shù)可能不能很好地滿足需求,這個時候就需要結(jié)合當(dāng)前使用連接池的原理、具體的連接池監(jiān)控數(shù)據(jù)和當(dāng)前的業(yè)務(wù)量作一個綜合的判斷,通過反復(fù)的幾次調(diào)試得到最終的調(diào)優(yōu)參數(shù)。

合理使用索引
索引一般情況下都是高效的。但是由于索引是以空間換時間的一種策略,索引本身在提高查詢效率的同時會影響插入、更新、刪除的效率,頻繁寫的表不宜建索引。

選擇合適的索引列,選擇在where,group by,order by,on從句中出現(xiàn)的列作為索引項,對于離散度不大的列沒有必要創(chuàng)建索引。?
主鍵已經(jīng)是索引了,所以primay key 的主鍵不用再設(shè)置unique唯一索引

索引類型?
主鍵索引 (PRIMARY KEY)?
唯一索引 (UNIQUE)?
普通索引 (INDEX)?
組合索引 (INDEX)?
全文索引 (FULLTEXT)

可以應(yīng)用索引的操作符?
大于等于?
Between?
IN?
LIKE 不以 % 開頭

不能應(yīng)用索引的操作符?
NOT IN?
LIKE %_ 開頭

如何選擇索引字段?
A:字段出現(xiàn)在查詢條件中,并且查詢條件可以使用索引?
B:通常對數(shù)字的索引和檢索要比對字符串的索引和檢索效率更高?
C:語句執(zhí)行頻率高,一天會有幾千次以上?
D:通過字段條件可篩選的記錄集很小?
無效索引?
A:盡量不要在 where 子句中對字段進行 null 值判斷,否則將導(dǎo)致引擎放棄使用索引而進行全表掃描?
B:應(yīng)盡量避免在 where 子句中使用 != 或 <> 操作符,否則將引擎放棄使用索引而進行全表掃描。?
C:應(yīng)盡量避免在 where 子句中使用 or 來連接條件,如果一個字段有索引,一個字段沒有索引,將導(dǎo)致引擎放棄使用索引而進行全表掃描?
select id from t where num=10 or Name = ‘a(chǎn)dmin’?
可以這樣查詢:?
select id from t where num = 10?
union?
select id from t where Name = ‘a(chǎn)dmin’?
union all 返回所有數(shù)據(jù),不管是不是重復(fù)。 union會自動壓縮,去除重復(fù)數(shù)據(jù)。

D:不做列運算?
where age + 1 = 10,任何對列的操作都將導(dǎo)致表掃描,它包括數(shù)據(jù)庫教程函數(shù)、計算表達式等?
E:查詢like,如果是 ‘%aaa’ 不會使用到索引

分表
分表方式?
水平分割(按行)、垂直分割(按列)

分表場景?
A: 根據(jù)經(jīng)驗,mysql表數(shù)據(jù)一般達到百萬級別,查詢效率就會很低。?
B: 一張表的某些字段值比較大并且很少使用??梢詫⑦@些字段隔離成單獨一張表,通過外鍵關(guān)聯(lián),例如考試成績,我們通常關(guān)注分數(shù),不關(guān)注考試詳情。

水平分表策略?
按時間分表:當(dāng)數(shù)據(jù)有很強的實效性,例如微博的數(shù)據(jù),可以按月分割。?
按區(qū)間分表:例如用戶表 1到一百萬用一張表,一百萬到兩百萬用一張表。?
hash分表:通過一個原始目標(biāo)id或者是名稱按照一定的hash算法計算出數(shù)據(jù)存儲的表名。

讀寫分離
當(dāng)一臺服務(wù)器不能滿足需求時,采用讀寫分離【寫: update/delete/add】的方式進行集群。?
一臺數(shù)據(jù)庫支持最大連接數(shù)是有限的,如果用戶的并發(fā)訪問很多,一臺服務(wù)器無法滿足需求,可以集群處理。mysql集群處理技術(shù)最常用的就是讀寫分離。

主從同步:數(shù)據(jù)庫最終會把數(shù)據(jù)持久化到磁盤,集群必須確保每個數(shù)據(jù)庫服務(wù)器的數(shù)據(jù)是一致的。從庫讀主庫寫,從庫從主庫上同步數(shù)據(jù)。?
讀寫分離:使用負載均衡實現(xiàn),寫操作都往主庫上寫,讀操作往從服務(wù)器上讀。

緩存
緩存分類?
本地緩存:HashMap/ConcurrentHashMap、Ehcache、Guava Cache等?
緩存服務(wù):redis/Tair/Memcache等

使用場景?
短時間內(nèi)相同數(shù)據(jù)重復(fù)查詢多次且數(shù)據(jù)更新不頻繁,這個時候可以選擇先從緩存查詢,查詢不到再從數(shù)據(jù)庫加載并回設(shè)到緩存的方式。此種場景較適合用單機緩存。?
高并發(fā)查詢熱點數(shù)據(jù),后端數(shù)據(jù)庫不堪重負,可以用緩存來扛。

緩存作用?
減輕數(shù)據(jù)庫的壓力,減少訪問時間。

緩存選擇?
如果數(shù)據(jù)量小,并且不會頻繁地增長又清空(這會導(dǎo)致頻繁地垃圾回收),那么可以選擇本地緩存。具體的話,如果需要一些策略的支持(比如緩存滿的逐出策略),可以考慮Ehcache;如不需要,可以考慮HashMap;如需要考慮多線程并發(fā)的場景,可以考慮ConcurentHashMap。?
其他情況,可以考慮緩存服務(wù)。目前從資源的投入度、可運維性、是否能動態(tài)擴容以及配套設(shè)施來考慮,我們優(yōu)先考慮Tair。除非目前Tair還不能支持的場合(比如分布式鎖、Hash類型的value),我們考慮用Redis。

緩存穿透?
一般的緩存系統(tǒng),都是按照key去緩存查詢,如果不存在對應(yīng)的value,就應(yīng)該去后端系統(tǒng)查找(比?
如DB)。如果key對應(yīng)的value是一定不存在的,并且對該key并發(fā)請求量很大,就會對后端系統(tǒng)造?
成很大的壓力。這就叫做緩存穿透。

對查詢結(jié)果為空的情況也進行緩存,緩存時間設(shè)置短點,或者該key對應(yīng)的數(shù)據(jù)insert了之后清理緩存。

緩存并發(fā)?
有時候如果網(wǎng)站并發(fā)訪問高,一個緩存如果失效,可能出現(xiàn)多個進程同時查詢DB,同時設(shè)置緩存的情況,?
如果并發(fā)確實很大,這也可能造成DB壓力過大,還有緩存頻繁更新的問題。

對緩存查詢加鎖,如果KEY不存在,就加鎖,然后查DB入緩存,然后解鎖;其他進程如果發(fā)現(xiàn)有鎖就?
等待,然后等解鎖后返回數(shù)據(jù)或者進入DB查詢。

緩存雪崩(失效)?
當(dāng)緩存服務(wù)器重啟或者大量緩存集中在某一個時間段失效,這樣在失效的時候,也會給后端系統(tǒng)(比如DB)?
帶來很大壓力。?
不同的key,設(shè)置不同的過期時間,讓緩存失效的時間點盡量均勻.

防止緩存空間不夠用?
① 給緩存服務(wù),選擇合適的緩存逐出算法,比如最常見的LRU。?
② 針對當(dāng)前設(shè)置的容量,設(shè)置適當(dāng)?shù)木渲?,比?0G的緩存,當(dāng)緩存數(shù)據(jù)達到8G的時候,就開始發(fā)出報警,提前排查問題或者擴容。?
③ 給一些沒有必要長期保存的key,盡量設(shè)置過期時間。

我們看下圖,在WebServer(Dao層)和DB之間加一層cache,這層cache一般選取的介質(zhì)是內(nèi)存,因為我們都知道存入數(shù)據(jù)庫的數(shù)據(jù)都具有持久化的特點,那么讀寫會有磁盤IO的操作,內(nèi)存的讀寫速度遠比磁盤快得多。(選用存儲介質(zhì),提高訪問速度:內(nèi)存>>磁盤;減少磁盤IO的操作,減少重復(fù)查詢,提高吞吐量)

常用開源的緩存工具有:ehcache、memcache、redis。

ehcache 是一個純Java的進程內(nèi)緩存框架,hibernate使用其做二級緩存。同時,ehcache可以通過多播的方式實現(xiàn)集群。本人主要用于本地的緩存,數(shù)據(jù)庫上層的緩存。?
memcache是一套分布式的高速緩存系統(tǒng),提供key-value這樣簡單的數(shù)據(jù)儲存,可充分利用CPU多核,無持久化功能。在做web集群中可以用做session共享,頁面對象緩存。?
redis高性能的key-value系統(tǒng),提供豐富的數(shù)據(jù)類型,單核CPU有抗并發(fā)能力,有持久化和主從復(fù)制的功能。本人主要使用redis的redis sentinel,根據(jù)不同業(yè)務(wù)分為多組。

redis注意事項?
A:在增加 key 的時候盡量設(shè)置過期時間,不然 Redis Server 的內(nèi)存使用會達到系統(tǒng)物理內(nèi)存的最大值,導(dǎo)致 Redis 使用 VM 降低系統(tǒng)性能;?
B:Redis Key 設(shè)計時應(yīng)該盡可能短,Value 盡量不要使用復(fù)雜對象;?
C:將對象轉(zhuǎn)換成 JSON 對象(利用現(xiàn)成的 JSON 庫)后存入 Redis;?
D:將對象轉(zhuǎn)換成 Google 開源二進制協(xié)議對象(Google Protobuf,和 JSON 數(shù)據(jù)格式類似,但是因為是二進制表現(xiàn),所以性能效率以及空間占用都比 JSON 要小;缺點是 Protobuf 的學(xué)習(xí)曲線比 JSON 大得多);?
E:Redis 使用完以后一定要釋放連接。

讀取緩存中是否有相關(guān)數(shù)據(jù),如果緩存中有相關(guān)數(shù)據(jù),則直接返回,這就是所謂的數(shù)據(jù)命中“hit”?
如果緩存中沒有相關(guān)數(shù)據(jù),則從數(shù)據(jù)庫讀取相關(guān)數(shù)據(jù),放入緩存中,再返回。這就是所謂的數(shù)據(jù)未命中“miss”

緩存的命中率 = 命中緩存請求個數(shù)/總緩存訪問請求個數(shù) = hit/(hit+miss)?
/*java框架項目案例 www.1b23.com*/

NOSQL
與緩存的區(qū)別?
先說明一下,這里介紹的和緩存不一樣,雖然redis等也可以用來做數(shù)據(jù)存儲方案(比如Redis或者Tair),但NoSql是把它作為DB來用。如果當(dāng)作DB來用,需要有效保證數(shù)據(jù)存儲方案的可用性、可靠性。

使用場景?
需要結(jié)合具體的業(yè)務(wù)場景,看這塊業(yè)務(wù)涉及的數(shù)據(jù)是否適合用NoSQL來存儲,對數(shù)據(jù)的操作方式是否適合用NoSQL的方式來操作,或者是否需要用到NoSQL的一些額外特性(比如原子加減等)。?
如果業(yè)務(wù)數(shù)據(jù)不需要和其他數(shù)據(jù)作關(guān)聯(lián),不需要事務(wù)或者外鍵之類的支持,而且有可能寫入會異常頻繁,這個時候就比較適合用NoSQL(比如HBase)。?
比如,美團點評內(nèi)部有一個對exception做的監(jiān)控系統(tǒng),如果在應(yīng)用系統(tǒng)發(fā)生嚴(yán)重故障的時候,可能會短時間產(chǎn)生大量exception數(shù)據(jù),這個時候如果選用MySQL,會造成MySQL的瞬間寫壓力飆升,容易導(dǎo)致MySQL服務(wù)器的性能急劇惡化以及主從同步延遲之類的問題,這種場景就比較適合用Hbase類似的NoSQL來存儲。?
視圖/存儲過程?
普通業(yè)務(wù)邏輯盡量不要使用存儲過程,定時任務(wù)或報表統(tǒng)計函數(shù)可以根據(jù)團隊資源情況采用存儲過程處理。

GVM調(diào)優(yōu)
通過監(jiān)控系統(tǒng)(如沒有現(xiàn)成的系統(tǒng),自己做一個簡單的上報監(jiān)控的系統(tǒng)也很容易)上對一些機器關(guān)鍵指標(biāo)(gc time、gc count、各個分代的內(nèi)存大小變化、機器的Load值與CPU使用率、JVM的線程數(shù)等)的監(jiān)控報警,也可以看gc log和jstat等命令的輸出,再結(jié)合線上JVM進程服務(wù)的一些關(guān)鍵接口的性能數(shù)據(jù)和請求體驗,基本上就能定位出當(dāng)前的JVM是否有問題,以及是否需要調(diào)優(yōu)。

異步/多線程
針對某些客戶端的請求,在服務(wù)端可能需要針對這些請求做一些附屬的事情,這些事情其實用戶并不關(guān)心或者用戶不需要立即拿到這些事情的處理結(jié)果,這種情況就比較適合用異步的方式處理這些事情。

異步作用?
A:縮短接口響應(yīng)時間,使用戶的請求快速返回,用戶體驗更好。?
B:避免線程長時間處于運行狀態(tài),這樣會引起服務(wù)線程池的可用線程長時間不夠用,進而引起線程池任務(wù)隊列長度增大,從而阻塞更多請求任務(wù),使得更多請求得不到技術(shù)處理。?
C:線程長時間處于運行狀態(tài),可能還會引起系統(tǒng)Load、CPU使用率、機器整體性能下降等一系列問題,甚至引發(fā)雪崩。異步的思路可以在不增加機器數(shù)和CPU數(shù)的情況下,有效解決這個問題。

異步實現(xiàn)?
A:額外開辟線程,這里可以采用額外開辟一個線程或者使用線程池的做法,在IO線程(處理請求響應(yīng))之外的線程來處理相應(yīng)的任務(wù),在IO線程中讓response先返回。?
B:使用消息隊列(MQ)中間件服務(wù)


分享名稱:數(shù)據(jù)庫SQL優(yōu)化
新聞來源:http://weahome.cn/article/psgseo.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部