1. 程式人生 > >資料庫設計以及優化注意的問題

資料庫設計以及優化注意的問題

總的來說,mysql優化:
1、索引和sql語句優化,查詢優化
2、資料庫表結構優化
3、資料庫架構優化
4、演算法優化
5、硬體升級

一、資料庫結構的設計

遇到大資料併發訪問 ——>合理的資料冗餘

為了保證資料庫的一致性和完整性,在邏輯設計的時候往往會設計過多的表間關聯,儘可能的降低資料的冗餘。(例如使用者表的地區,我們可以把地區另外存放到一個地區表中)如果資料冗餘低,資料的完整性容易得到保證,提高了資料吞吐速度,保證了資料的完整性,清楚地表達資料元素之間的關係。
而對於多表之間的關聯查詢(尤其是大資料表)時,其效能將會降低,同時也提高了客戶端程式的程式設計難度,因此,物理設計需折衷考慮,根據業務規則,確定對關聯表的資料量大小、資料項的訪問頻度,對此類資料表頻繁的關聯查詢應適當提高資料冗餘設計但增加了表間連線查詢的操作,也使得程式的變得複雜,==為了提高系統的響應時間,合理的資料冗餘也是必要的==。

表的設計具體注意的問題:

1、資料行的長度不要超過8020位元組,如果超過這個長度的話在物理頁中這條資料會佔用兩行從而造成儲存碎片,降低查詢效率。

2、能夠用數字型別的欄位儘量選擇數字型別而不用字串型別的(電話號碼),這會降低查詢和連線的效能,並會增加儲存開銷。這是因為引擎在處理查詢和連接回逐個比較字串中每一個字元,而對於數字型而言只需要比較一次就夠了。

3、對於不可變字元型別char和可變字元型別varchar 都是8000位元組,char查詢快,但是耗儲存空間,varchar查詢相對慢一些但是節省儲存空間。在設計欄位的時候可以靈活選擇,例如使用者名稱、密碼等長度變化不大的欄位可以選擇CHAR,對於評論等長度變化大的欄位可以選擇VARCHAR。

4、欄位的長度在最大限度的滿足可能的需要的前提下,應該儘可能的設得短一些,這樣可以提高查詢的效率,而且在建立索引的時候也可以減少資源的消耗。

二、查詢的優化

  1. 保證在實現功能的基礎上,儘量減少對資料庫的訪問次數;
  2. 通過搜尋引數,儘量減少對錶的訪問行數,最小化結果集,從而減輕網路負擔;
  3. 能夠分開的操作儘量分開處理,提高每次的響應速度;
  4. 在資料視窗使用SQL時,儘量把使用的索引放在選擇的首列;
  5. 演算法的結構儘量簡單;
  6. 在查詢時,不要過多地使用萬用字元如SELECT * FROM T1語句,要用到幾列就選擇幾列如:SELECT COL1,COL2 FROM T1;在可能的情況下儘量限制儘量結果集行數如:SELECT TOP 300 COL1,COL2,COL3 FROM T1,因為某些情況下使用者是不需要那麼多的資料的。

在沒有建索引的情況下,資料庫查詢某一條資料,就必須進行全表掃描了,對所有資料進行一次遍歷,查找出符合條件的記錄。在資料量比較小的情況下,也許看不出明顯的差別,但是當資料量大的情況下,這種情況就是極為糟糕的了。
優化查詢最重要的就是,儘量使語句符合查詢優化器的規則避免全表掃描而使用索引查詢。

具體要注意的:

  1. 應儘量避免在 where 子句中對欄位進行 null 值判斷,否則將導致引擎放棄使用索引而進行全表掃描,如:
     select id from t where num is null

可以在num上設定預設值0,確保表中num列沒有null值,然後這樣查詢:

select id from t where num=0

2.應儘量避免在 where 子句中使用!=或<>操作符,否則將引擎放棄使用索引而進行全表掃描。優化器將無法通過索引來確定將要命中的行數,因此需要搜尋該表的所有行。

3.應儘量避免在 where 子句中使用 or 來連線條件,否則將導致引擎放棄使用索引而進行全表掃描,如:
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 也要慎用,因為IN會使系統無法使用索引,而只能直接搜尋表中的資料。如:
select id from t where num in(1,2,3)
對於連續的數值,能用 between 就不要用 in 了:
select id from t where num between 1 and 3

5.儘量避免在索引過的字元資料中,使用非打頭字母搜尋。這也使得引擎無法利用索引。
見如下例子:
SELECT * FROM T1 WHERE NAME LIKE ‘%L%’
SELECT * FROM T1 WHERE SUBSTING(NAME,2,1)=’L’
SELECT * FROM T1 WHERE NAME LIKE ‘L%’

即使NAME欄位建有索引,前兩個查詢依然無法利用索引完成加快操作,引擎不得不對全表所有資料逐條操作來完成任務。而第三個查詢能夠使用索引來加快操作。

6.必要時強制查詢優化器使用某個索引,如在 where 子句中使用引數,也會導致全表掃描。因為SQL只有在執行時才會解析區域性變數,但優化程式不能將訪問計劃的選擇推遲到執行時;它必須在編譯時進行選擇。然而,如果在編譯時建立訪問計劃,變數的值還是未知的,因而無法作為索引選擇的輸入項。如下面語句將進行全表掃描:
select id from t where [email protected]
可以改為強制查詢使用索引:
select id from t with(index(索引名)) where [email protected]

7.應儘量避免在 where 子句中對欄位進行表示式操作,這將導致引擎放棄使用索引而進行全表掃描。如:
SELECT * FROM T1 WHERE F1/2=100
應改為:
SELECT * FROM T1 WHERE F1=100*2

SELECT * FROM RECORD WHERE SUBSTRING(CARD_NO,1,4)=’5378’
應改為:
SELECT * FROM RECORD WHERE CARD_NO LIKE ‘5378%’

SELECT member_number, first_name, last_name FROM members
WHERE DATEDIFF(yy,datofbirth,GETDATE()) > 21
應改為:
SELECT member_number, first_name, last_name FROM members
WHERE dateofbirth < DATEADD(yy,-21,GETDATE())
即:任何對列的操作都將導致表掃描,它包括資料庫函式、計算表示式等等,查詢時要儘可能將操作移至等號右邊。

8.應儘量避免在where子句中對欄位進行函式操作,這將導致引擎放棄使用索引而進行全表掃描。如:
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
應改為:
select id from t where name like ‘abc%’
select id from t where createdate>=’2005-11-30’ and createdate<’2005-12-1’

9.不要在 where 子句中的“=”左邊進行函式、算術運算或其他表示式運算,否則系統將可能無法正確使用索引。

10.在使用索引欄位作為條件時,如果該索引是複合索引,那麼必須使用到該索引中的第一個欄位作為條件時才能保證系統使用該索引,否則該索引將不會被使用,並且應儘可能的讓欄位順序與索引順序相一致。

11.很多時候用 exists是一個好的選擇:

elect num from a where num in(select num from b)
用下面的語句替換:
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)
兩者產生相同的結果,但是後者的效率顯然要高於前者。因為後者不會產生大量鎖定的表掃描或是索引掃描。

如果你想校驗表裡是否存在某條紀錄,不要用count(*)那樣效率很低,而且浪費伺服器資源。可以用EXISTS代替。如:
IF (SELECT COUNT(*) FROM table_name WHERE column_name = ‘xxx’)
可以寫成:
IF EXISTS (SELECT * FROM table_name WHERE column_name = ‘xxx’)

經常需要寫一個T_SQL語句比較一個父結果集和子結果集,從而找到是否存在在父結果集中有而在子結果集中沒有的記錄,如:
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)

三種寫法都可以得到同樣正確的結果,但是效率依次降低。

12.儘量使用表變數來代替臨時表。如果表變數包含大量資料,請注意索引非常有限(只有主鍵索引)。

13.避免頻繁建立和刪除臨時表,以減少系統表資源的消耗。

14.臨時表並不是不可使用,適當地使用它們可以使某些例程更有效,例如,當需要重複引用大型表或常用表中的某個資料集時。但是,對於一次性事件,最好使用匯出表。

15.在新建臨時表時,如果一次性插入資料量很大,那麼可以使用 select into 代替 create table,避免造成大量 log ,以提高速度;如果資料量不大,為了緩和系統表的資源,應先create table,然後insert。

16.如果使用到了臨時表,在儲存過程的最後務必將所有的臨時表顯式刪除,先 truncate table ,然後 drop table ,這樣可以避免系統表的較長時間鎖定。
17.在所有的儲存過程和觸發器的開始處設定 SET NOCOUNT ON ,在結束時設定 SET NOCOUNT OFF 。無需在執行儲存過程和觸發器的每個語句後向客戶端傳送 DONE_IN_PROC 訊息。

18.儘量避免大事務操作,提高系統併發能力。

19.儘量避免向客戶端返回大資料量,若資料量過大,應該考慮相應需求是否合理。
20. 避免使用不相容的資料型別。例如float和int、char和varchar、binary和varbinary是不相容的。資料型別的不相容可能使優化器無法執行一些本來可以進行的優化操作。例如:
SELECT name FROM employee WHERE salary > 60000
在這條語句中,如salary欄位是money型的,則優化器很難對其進行優化,因為60000是個整型數。我們應當在程式設計時將整型轉化成為錢幣型,而不要等到執行時轉化。

21.充分利用連線條件,在某種情況下,兩個表之間可能不只一個的連線條件,這時在 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
第二句將比第一句執行快得多。

22、使用檢視加速查詢
把表的一個子集進行排序並建立檢視,有時能加速查詢。它有助於避免多重排序 操作,而且在其他方面還能簡化優化器的工作。例如:
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

如果這個查詢要被執行多次而不止一次,可以把所有未付款的客戶找出來放在一個檢視中,並按客戶的名字進行排序:
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不執行SELECT DISTINCT函式,這樣就會減少很多不必要的資源

35.儘量不要用SELECT INTO語句。
SELECT INOT 語句會導致表鎖定,阻止其他使用者訪問該表。

上面我們提到的是一些基本的提高查詢速度的注意事項,但是在更多的情況下,往往需要反覆試驗比較不同的語句以得到最佳方案。最好的方法當然是測試,看實現相同功能的SQL語句哪個執行時間最少,但是資料庫中如果資料量很少,是比較不出來的,這時可以用檢視執行計劃,即:把實現相同功能的多條SQL語句考到查詢分析器,按CTRL+L看查所利用的索引,表掃描次數(這兩個對效能影響最大),總體上看詢成本百分比即可。

三、演算法優化

四、建立 高效的索引

建立索引一般有以下兩個目的:
==維護被索引列的唯一性==和==提供快速訪問表中資料的策略==

索引需要付出的代價和帶來的弊端:
一.增加了資料庫的儲存空間,
二.在插入和修改資料時要花費較多的時間(因為索引也要隨之變動);

一個沒有簇索引的表是按==堆結構==儲存資料,所有的資料均新增在表的尾部,而建立了簇索引的表,其資料在物理上會按照簇索引鍵的順序儲存,一個表只允許有一個簇索引,因此,根據B樹結構,可以理解新增任何一種索引均能提高按索引列查詢的速度,但會降低插入、更新、刪除操作的效能,尤其是當填充因子(Fill Factor)較大時。所以對索引較多的表進行頻繁的插入、更新、刪除操作,建表和索引時因設定較小的填充因子,以便在各資料頁中留下較多的自由空間,減少頁分割及重新組織的工作。

作為一條規則,我通常對邏輯主鍵使用唯一的成組索引,對系統鍵(作為儲存過程)採用唯一的非成組索引,對任何外來鍵列[欄位]採用非成組索引。

微軟的SQL SERVER提供了兩種索引:==聚集索引==(clustered index,也稱聚類索引、簇集索引)和==非聚集索引==(nonclustered index,也稱非聚類索引、非簇集索引)。
下面,我們舉例來說明一下聚集索引和非聚集索引的區別:

【聚簇索引】
平時習慣逛圖書館的童鞋可能比較清楚,如果你要去圖書館借一本書,最開始是去電腦裡面查書名然後根據書名來定位藏書在那個區,哪個書櫃,哪一行,第多少本。。。清晰明確,一目瞭然,因為藏書的結構與圖書室的位置,書架的順序,書本的擺放順序與書籍的編號都是從大到小一致的順序擺放的,所以很容易找到。比如,你的目標藏書在C區2櫃3排5倉,那麼你走到B區你就很快知道前面就快到了C區了,你直接奔著2櫃區就能找到了。 這就是雷同於聚簇索引的功效了。
聚簇索引,實際儲存的循序結構與資料儲存的物理機構是一致的,所以通常來說物理順序結構只有一種,那麼一個表的聚簇索引也只能有一個,通常預設都是主鍵,設定了主鍵,系統預設就為你加上了聚簇索引,當然有人說我不想拿主鍵作為聚簇索引,我需要用其他欄位作為索引,當然這也是可以的,這就需要你在設定主鍵之前自己手動的先新增上唯一的聚簇索引,然後再設定主鍵,這樣就木有問題啦。
總而言之,==聚簇索引是順序結構與資料儲存物理結構一致的一種索引,並且一個表的聚簇索引只能有唯一的一條。==

【非聚簇索引】
同樣的,如果你去的不是圖書館,而是某城市的商業性質的圖書城,那麼你想找的書就擺放比較隨意了,由於商業圖書城空間比較緊正,藏書通常按照藏書上架的先後順序來擺放的,所以如果查詢到某書籍放在C區2櫃3排5倉,但你可能要繞過F區,而不是A.B.C.D…連貫一致的,也可能同在C區的2櫃,書櫃上第一排是計算機類的書記,也可能最後一排就是醫學類書籍;

那麼對照著來看非聚簇索引的概念就比較好理解了,非==聚簇索引記錄的物理順序與邏輯順序沒有必然的聯絡,與資料的儲存物理結構沒有關係;一個表對應的非聚簇索引可以有多條,根據不同列的約束可以建立不同要求的非聚簇索引;==

【總結索引使用原則】
1:不要索引資料量不大的表,對於小表來講,表掃描的成本並不高。
2:不要設定過多的索引,在沒有聚集索引的表中,最大可以設定249個非聚集索引,過多的索引首先會帶來更大的磁碟空間,而且在資料發生修改時,對索引的維護是特別消耗效能的。
3:合理應用複合索引,有某些情況下可以考慮建立包含所有輸出列的覆蓋索引。
4:對經常使用範圍查詢的欄位,可能考慮聚集索引。
5:避免對不常用的列,邏輯性列,大欄位列建立索引。

相關推薦

資料庫設計以及優化注意的問題

總的來說,mysql優化: 1、索引和sql語句優化,查詢優化 2、資料庫表結構優化 3、資料庫架構優化 4、演算法優化 5、硬體升級 一、資料庫結構的設計 遇到大資料併發訪問 ——>合理的資料冗餘 為了保證資料庫的一致性和完整性,

電商資料庫設計優化學習筆記彙總

一、背景 這是我學習高效能可擴充套件的MySQL設計及架構優化的學習筆記,學習過程中還有很多不懂的地方,特別是負載均衡的問題,先跟著老師的節奏記下來。 課程設計電商常用的功能模組的資料庫設計,常見問題的資料庫解決方案。 專案背景:設計一個電商資料庫,完成正常購物。 二、準備工作

表單設計以及優化Tips的總結

無論是註冊流程、多頁問卷,還是簡單的資料錄入介面,表單都是數字化產品設計的重要組成部分。我們無時無刻都在使用表單(Form),在網上購物、郵件註冊、參與評論等等。不誇張的說,它已經成為了數字資訊時代不

資料庫設計優化總結(1)

一、資料庫的設計的幾點措施 1.關聯表的關聯欄位名稱必須相同。 2.欄位的定義的前兩位是表名,第三位是下劃線,保證規範。 3.常用欄位採用固定單詞,如id 4.如果只有一個索引,索引的名字希望和表名相同,如果是多個,那麼就用表明下劃線欄位名。 5.關聯欄位儘可能為數字型別。

資料庫設計中應注意的問題

引言資料庫設計是資訊系統設計的基礎,一個好的資料庫設計在滿足了軟體需求之外,還要易維護、易擴充等等要求。當然,對專家們反覆強調的資料的一致性、冗餘性、訪問效率等問題的解決,很大程度上取決於資料庫設計者的經驗和專業水平。但這不妨礙我們根據過去的經驗,從實用的角度給出資料庫設計所要要考慮的問題並儘可能給出相應的

unity網路實戰開發(叢林戰爭)-正式開發階段(016-資料庫設計以及登入處理)

使用工具:VS2017,unity3d使用語言:c#作者:Gemini_xujian參考:siki老師-《叢林戰爭》視訊教程上一篇文章中,已經完成了遊戲場景與開始介面UI的搭建,接下來將對資料庫和登入請求響應等操作進行處理。01-設計資料庫表(使用者表和戰績表)首先,我們需要

數據庫設計以及優化 - 分區表

單表 解決 自己 分布 文件 spa 數據庫 物理 mysql HASH 分區: 分區在實際使用過程中的缺點: 解決什麽問題? 回答:當mysql單表的數據庫過大時,數據庫的訪問速度會下降,“數據量大”問題的常見解決方案是&ld

這些Mysql基礎設計思路以及優化思路我都給你總結好了

%s mit 標記 總結 業務 增加 二叉 索引 基礎 1、定長和不定長要區分開   2、不常用的列和常用的列分開存   3、增加冗余,反範式化   4、btree索引,就是用樹形結構存儲在磁盤上,其中操作是用2分發,找一個中間點,然後把大比這個大的分在一邊,小的放在一邊,

Oracle資料庫設計時的注意事項

表是Oracle資料庫中最基本的物件之一。萬丈高樓從平地起,這個基礎物件對於資料庫來說,非常重要。因為其設計是否合理,直接跟資料庫的效能相關。從Oracle資料庫菜鳥到資料庫專家這個過程中,在表設計與管理上,或多或少,會犯一些錯誤。筆者今天就談談自己在這方面的經驗與教訓,或許能夠給大家一些警

資料庫設計優化和備份

目錄 一、資料庫設計 1.為什麼需要資料庫設計? 2.資料庫設計的3大正規化 3.資料庫設計的步驟 4.E-R圖也稱實體-關係圖(Entity Relationship Diagram) 5.實體之間的關係 二、資料庫優化 1.select 字句中避免使用(*)

資料庫索引設計優化

1.表的索引數量不應有上限,只要所有的SQL都能夠流暢的執行。 一個頁從磁碟讀取到資料緩衝池中,一個頁包含多條記錄,我們可能需要該頁上的所有行或一部分行或一行,但花費的成本都相同,約10ms. 在計算領域中, 10ms是一個很長的時間。 10ms怎麼計算出來的:排隊時間 + 尋道時間 +

資料庫mysql優化注意點/JVM調優

1.sql語句,在使用select時候,指定要查詢的列名,避免使用 “*” 2.sql查詢一條或者幾條資料,使用limit0,1進行查詢擷取,因為limit會擷取到滿足條件資料後,立刻停止無用的sql繼續查詢 3.多條級聯查詢效率,合理使用 冗餘 欄位,儘量使用單表操作(另外,也可查詢都可單

高效能可擴充套件 MySQL資料庫架構設計優化

第1章 資料庫開發規範的制定 俗話說:“沒有規矩不成方圓”。這一章,我們就先來制定資料庫開發的各種規範,包括:資料庫命名規範、資料庫基本設計規範、資料庫索引設計規範、資料庫欄位設計規範、SQL開發規範以及資料庫操作規範。通過這些規範的制定可以指導並規範我們後續的開發工作,為我們以後的工作提供一個良好的基礎。.

hive的查詢注意事項以及優化總結

Hive是將符合SQL語法的字串解析生成可以在Hadoop上執行的MapReduce的工具。使用Hive儘量按照分散式計算的一些特點來設計sql,和傳統關係型資料庫有區別, 所以需要去掉原有關係型資料庫下開發的一些固有思維。 基本原則: 1:儘量儘早地過濾資料,減少

Unity實戰篇:移植遊戲到安卓平臺的注意事項及其例項(四)(物件池概念的引入以及優化

1.物件池基礎概念的瞭解(必看) 2.針對專案來進行嵌入 using System.Collections; using System.Collections.Generic; using UnityEngine; using Unit

Django_xAdmin線上教育平臺(一)之專案結構、資料庫設計以及xadmin的配置

django專案的目錄結構:   dj_education資料夾:         settings.py:django專案的全域性配置         url.py:url配置  templates資料夾:存放html檔案  manage.py:專案啟動的檔案

高效能mysql(二)schema設計以及sql執行、優化

1.索引覆蓋:因為使用B+TREE儲存索引資料(索引也是資料庫的資料),因為葉子節點上儲存著資料,其他索引也是通過主鍵去查詢資料,如果可以直接把索引的資料讀出使用而不用再次進入資料庫表中進行查詢操作,可以極大地提高效率(當然被查詢的資料也必須在索引這個資料結構中)。注:索引資料是索引的索引集合(包括

【 專欄 】- 資料庫實戰開發設計優化

作者:楊秀璋 學歷:本科-北京理工大學            碩士-北京理工大學 現任教於貴財財經大學資訊學院 http://www.eastmountyxz.com 簡介:自幼受貴州大山的薰陶,養成了誠實質樸的性格。經過寒窗苦讀,考入BIT,為完成自己的教師夢,放棄IT、航天等工

資料庫優化例項以及優化的小技巧

1.對查詢進行優化,應儘量避免全表掃描,首先應考慮在 where 及 order by 涉及的列上建立索引。 2.應儘量避免在 where 子句中對欄位進行 null 值判斷,否則將導致引擎放棄使用索引而進行全表掃描,如: select id from t where num is null 可以在num

資料庫設計需要注意什麼

一、基礎規範: 1. 必須使用InnoDB儲存引擎    解讀:支援事務、行級鎖、併發效能更好、CPU及記憶體快取頁優化使得資源利用率更高 2. 新庫預設使用utf8mb4字符集    解讀:utf8mb4是utf8的超集,emoji表情以及