數據庫優化
1.主要性能瓶頸
A.磁盤I/O
B.內存
C.網絡佔用
B.CPU處理
2.造成瓶頸的可能性有哪些
連接次數
磁盤讀取量
磁盤寫入量
傳輸數據塊大小
存儲量大小
響應時間快慢
3.行業需求主要有哪些(一般情況下)
門戶系統——面向大衆,連接次數很多,存儲量很小,讀很頻密,寫的可能性低,響應時間要求高
博客系統——面向大衆,連接次數較多,存儲量較小,讀較頻密,寫入量中等,傳輸數據塊大,響應時間要求一般
財務系統——內部用較多,連接次數少,傳輸數據大,讀寫週期長,響應時間要求一般
4.數據庫類型差異
關係型數據庫
XML數據庫
5.什麼情況容易引發數據庫性能故障
數據庫邏輯結構不合理
索引設計不合理
數據計算衝突
連接次數過多
讀取數據塊過大
SQL優化——
通用優化手段——
{
查詢目標集儘可能的小
避免排序和儘可能少排序,大數據量排序用臨時表分段去排,內存操作比硬盤操作快多了
}
索引——合理的索引設計建立在對各種查詢的分析和預測上
{
索引定義:
索引是表數據抽象出來的隱藏表,無法直接使用,但在操作定義了索引的字段的時候自動使用這張隱藏表來加速操作。
索引類型:
1.BTree索引,BTree根據內容將數據劃分爲集合和子集來工作,適合含有大量不同值的字段,如ID、Name
2.位圖索引,位圖索引的排序方式對於只包含很少不同值的字段更爲有效,適合只包含很少不同值的字段,如性別、是或非
索引的優點:
1.當然是速度,大大地加快檢索速度
2.加快表之間的連接速度
3.減少分組和排序時間
4.使用優化隱藏器提高系統性能
5.唯一性索引(unique)可確保數據的唯一性
索引的缺點:
1.索引會影響增刪改的速度,當數據庫進行增刪改操作時,索引也要進行動態維護,如果增刪改的需求比較大,那麼最好減 少索引,否則在大數據量情況下,動態維護索引佔用的時間將會很多。
2.建立索引就像給數據加了一個唯一編號字段(當然沒那麼簡單),也是要佔用物理存儲空間的,聚集索引佔用的更大(表 副本 + 索引頁 約等於表大小的120%),如果索引建立太多將會使數據庫變得龐大。
3.索引將在實際使用中由於索引變更而在索引頁產生索引碎片和排列邏輯混亂,需要定期整理索引
索引的創建規則:
1.常用查詢字段創建索引,如主鍵、外鍵,但當主鍵是ID並且該ID非其它表的外鍵時,最好將它只設置爲唯一非聚集索引, 而將使用比較多的查詢字段,例如Name之類 設置爲聚集索引
2.儘量選擇使用可能最頻密的列爲組合索引的前導列,使關鍵查詢形成索引覆蓋,而經常同時存取多列,且每列都含有重複 值則需要考慮建立組合索引
3.經常需要範圍搜索(Between、>、<、>=、<=)的字段創建聚簇索引,如績效統計系統的上下班時段計算
4.經常需要排序(Order By、Group By)的字段創建聚簇索引,如績效統計系統的業績排序
5.進行多表連接查詢的時候儘量使用帶有索引的表
6.避免在where條件存在對字段的類型轉換、運算等操作語句,where條件對字段操作的話,SQL將無法使用索引,整個語句的 搜索都將用表搜索完成
7.in和or子句常會使工作表、索引失去應有效果,如果不會產生大量重複值的話,可以考慮稍微犧牲一點內存,將子句拆開 ,拆開的子句儘量去使用索引來提高效率
8.如果SQL使用頻率很高,又無法很好地使用索引,那麼最好將SQL做成存儲過程來提高效率
非查詢關鍵字段遠離索引,如員工表的“住址”之類
9.數據量很少的字段遠離索引,如中小型公司的“部門名稱”,但是得考慮查詢的可能性,比較低的話,使用其主鍵與查詢 高的表做個關聯就夠了
10.數據類型爲text、image、bit之類大數據集的字段儘量不建立索引,佔用數據庫空間太大,效果也不明顯
11.當增刪改性能需求大於查詢需求的時候不建立索引,索引對增刪改的性能影響很大
解決辦法:
1.數據庫分離成查詢專用數據庫和修改專用數據庫,兩個數據庫分別進行優化處理。就是用硬件或空間來交換效率,相對硬 件資源、網絡資源的要求就會提升。
2.如果硬件無法提升,空間和網絡資源有餘(需要控制硬件支出),那麼將查詢操作儘量集中到一個查詢專用關聯表,整表 都是主鍵和外鍵,專用於優化查詢,犧牲部分硬盤空間換取一定程序的高效。
優化方法:
1.設計數據庫的時候根據系統的檢索要求充分考慮索引覆蓋
2.如果數據庫支持,使用索引優化嚮導
3.定期整理索引碎片,甚至重建索引
索引的使用和操作:
建立索引
CREATE INDEX <索引名> on <表名>(<字段名>)——index默認爲BTree索引
CREATE INDEX <索引名> on <表名>(<字段名>,<字段名>)——建立BTree類型組合索引
CREATE bitmap INDEX <索引名> on <表名>(<字段名>)——建立位圖索引
CREATE UNIQUE INDEX <索引名>
刪除索引
DROP INDEX <表名或視圖名>.<索引名>——SQL Server
DROP INDEX <索引名>——Oracle和DB2
ALTER TABLE <表名> DROP INDEX <索引名>——MySQL
sp_helpindex <表名>——查看索引信息
sp_rename
dbcc showcontig——顯示錶信息(包括索引碎片情況)
dbcc dbreindex——重建指定數據庫中一個或多個索引
dbcc indexdefrag——整理指定表或視圖的聚集索引或輔助索引的碎片
}
視圖——
{
視圖定義:
視圖是由一張或多張表數據組合而成的虛擬表,對於數據庫本身來說,它是內置的SQL語句。它對數據庫外界來說跟實際的表 沒區別,可以直接進行操作,多用來簡化常用組合查詢。也有爲了安全性考慮,爲了隱藏部分數據而專門做視圖的情況。
視圖的優點:
1.數據可自由定製,可以針對最常用數據集中查詢
2.簡化操作,視圖本身就是一個查詢結果,複雜查詢可以由視圖完成,對視圖本身的簡單操作就可以得到複雜查詢的結果
3.當數據庫變更或者應用程序邏輯發生了變更,可以使用視圖對兩者的變化進行兼容,保持各自獨立性,減低變更成本
4.可以按使用者權限創建一個專用視圖,可以將使用者和底層數據分離開來,增強數據庫安全性
視圖的使用和操作:
創建視圖
CREATE VIEW <視圖名> AS
SELECT <字段名>,<字段名> FROM <表名>,<表名> WHERE <條件>
修改視圖
ALERT VIEW <視圖名> AS
SELECT <字段名>,<字段名> FROM <表名>,<表名> WHERE <條件>
複雜視圖之排序
CREATE VIEW <視圖名> AS
SELECT <字段名>,<字段名> FROM <表名>,<表名> WHERE <條件> ORDER BY <條件> <ASC|DESC>
調用系統存儲過程更改視圖名
SP_RENAME VIEW <舊視圖名>,<新視圖名>
查看視圖信息
SP_HELP
SP_HELPTEXT
SP_DEPENDS
刪除視圖
DROP VIEW <視圖A>,<視圖B>
視圖可選參數:
加密——WITH ENCRYPTION(對你的視圖查詢語句進行加密,以保證數據庫只有你自己能操作)
CREATE VIEW <視圖名> AS WITH ENCRYPTION SELECT <字段名>,<字段名> FROM <表名>,<表名>
條件檢查——WITH CHECK OPTION(將根據WHERE條件子句來判斷選擇,不符合數據的修改將被拒絕)
CREATE VIEW <視圖名> AS SELECT <字段名>,<字段名> FROM <表名>,<表名> WHERE <條件> WITH CHECK OPTION
}
存儲過程——
{
存儲過程定義:
顧名思義就是存儲在數據庫裏面的操作過程——的定義,也可以認爲是被數據庫自身所接受(編譯並優化)的SQL
存儲過程的優點:
1.快速,它是被數據庫已編譯且優化過的
2.靈活,它更像程序而不是SQL語句,可以完成複雜的判斷運算
3.降低網絡資源佔用,遠程應用服務器只要調用一下存儲過程就可以完成複雜動作,減少了複雜SQL語句的傳輸
4.應用服務和數據庫之間的緩衝,部分運算規則可以做成存儲過程,當數據庫改動或者應用程序更改可以將兩者分離開
存儲過程的分類:
1.以“SP_”開頭的是系統存儲過程,用來進行系統的設定或者信息查看
例如:SP_HELP、SP_HELPTEXT、SP_HELPINDEX
2.以“XP_”開頭的是擴展存儲過程,用來調用操作系統提供的功能
例如:XP_CMDSHELL 'ping 192.168.0.1'
3.用戶自己定義的存儲過程,這纔是我們所說的存儲過程
存儲過程的使用:
創建存儲過程
CREATE PROCEDURE [<擁有者>.]<存儲過程名> [參數1....參數1024]
[WITE <RECOMPILE | ENCRYPTION | RECOMPILE,ENCRYPTION>]
[FOR REPLICATION]
AS 程序行
樣例:
出版商圖書管理系統:
需求1——指定使用人爲作者(author),而不是出版商(publisher)
需求2——存儲過程加密
需求3——訂單履歷表.以往賣出數量 + 訂單記錄表.本月賣出數量 = 返回值:銷售總量
需求4——書表.單價 × 銷售總量 = 返回值:總銷售額
需求5——書表.成本 × 銷售總量 = 返回值:總成本
需求6——總銷售額 - 總成本 = 返回值:純利潤
需求7——純利潤 × 合約表.作者利潤比例 = 返回值:作者收益
Oracle寫法——
CREATE PROCEDURE author.p_book_profit
@b_id int
@b_sale_count int output
@b_total_sales money output
@b_total_cost money output
@b_total_profit money output
@b_author_profit money output
WITH ENCRYPTION
AS
SELECT
@b_sale_count,
@b_total_sales=(price * @b_sale_count),
@b_total_cost=(cost * @b_sale_count),
@b_total_profit=(@b_total_sales-@b_total_cost)
@b_author_profit=(@b_total_profit * per)
FROM
(SELECT @b_sale_count=(COUNT(o_r.*) + COUNT(o_n.*))
FROM order_recode o_r,order_now o_n
WHERE @b_id = o_n.bookid and o_n.bookid = o_r.bookid),
(SELECT books.price price, books.cost cost
FROM books
WHERE @b_id=books.bookid),
(SELECT pactum.profit_author_per per
FROM pactum
WHERE @b_id=pactum.bookid)
SQLServer寫法——
}
表分區
{
}
Oracle優化——
{
nologging
註釋優化
}