首先來看一下資料庫優化的方式以及優化後的效果和成本。
上面你也看到了sql及索引優化成本低而且效果高,那麼如何優化sql呢?
那麼如何發現有問題的sql呢?(這裡我使用mysql舉例)
你可以開啟mysql的慢查詢日誌對有效率問題的sql進行監控
-- 開啟慢查詢日誌
setglobal slow_query_log=
on;
慢查詢日誌中包含sql,sql執行時間以及其他執行資訊。
你也可以使用mysql慢查詢日誌分析工具pt-query-digest,找到
1.查詢次數多且占用時間長的sql,通常為pt分析的前幾個查詢。
2.io大的sql(資料庫中的資料是一頁一頁儲存的,每查詢一頁就是一次io,io費時)
3.未命中索引的sql。
然後可以通過explain sql語句 分析sql的執行計畫。
count()和max()
-- 優化max()函式,像這類的函式需要遍歷一遍對應的字段,可以在該字段上新增索引,快速查詢
explain
select
max(payment_date)
from payment;
create
index idx_paydate on payment(payment_data)
;//給payment_date建立索引(覆蓋索引)
平時我們使用都是使用count(*)計算所有行,count(字段)就是計算該字段上只要不為null就+1,為null就不+。下面我們看看,如果有一張電影表,記錄所有電影和該電影上映的時間。
-- 在一條sql中同時查出2023年和2023年電影的數量--優化count()函式
select
count
(release_year=
'2006'
ornull)as
'2023年電影數量',count
(release_year=
'2007'
ornull)as
'2023年電影數量'
from film;
-- 上面or null,如果=2006,就是1 or null true 就+1 如果!=2006 然後就是0 or null得到null,null是不會+1計數的
-- count()統計的是非空的資料,所以只有為null才不計算,所以就算false也會計算,所以上面or null,就是除了2006就是null不計算了
子查詢優化
通常情況下,需要避免子查詢,改為連線查詢,比如使用in,因為外層沒查詢一次,子查詢in內部就會遍歷查詢一遍。浪費時間。
//查詢sandra出演的所有影片
explain
select title,release_year,length from film
where film_id in
(select film_id from film_actor where actor_id in
(select actor_id from actor where first_name=
'sandra'))
;
exist和in
在必須寫子查詢的情況就會有兩種情況,誰在外層,誰在裡層?
最好結果就是:最優化匹配原則:拿最小記錄匹配大記錄。
group by的優化
explain
select actor.first_name,actor_last_name,
count(*
)from sakila.film_actor
inner
join sakila.actor using
(actor_id)
group
by film_actor.actor_id;
因為上面**首先連線查詢,最後group by,group by 放在最外層,這裡會建立臨時表給分組用。
//改後 結合子查詢 索引
explain
select actor.first_name,actor.last_name,c.cnt from sakila.actor
inner
join
(select actor_id,
count(*
)as cnt from sakila.film_actor group
by actor_id)
as c using
(actor_id)
;
這裡使用子查詢在內部就直接分組查詢,然後與外層連線查詢就不會涉及到建立臨時表。
像如果需要新增where條件,最後在子查詢內部來新增,盡量不要寫在最外面
limit優化
limit常用於分頁處理,時常會伴隨order by 從句使用,因此大多時候會使用filesorts這樣會造成大量的io問題。
//檔案排序,io大
explain
select film_id,description from sakila.film order
by title limit50,
5;
1.優化:使用有索引的列或主鍵進行order by操作(order by film_id) 但是優化1在掃瞄的時候還是會全部掃瞄,io大,所以可以使用下面where條件的方式來避免掃瞄太多的資料
2.記錄上次返回的主鍵,在下次查詢的時候用主鍵過濾,避免了資料量大時掃瞄過多的記錄 select film_id,description from sakila.film where film_id>55 and film_id<=60 order by film_id
limit 1,5; 頁數越大,io越大
注意:上面where條件中的film_id必須是連續的,否則可能會錯過資料,如果這個id是不連續的,可以在建立表時新增乙個連續欄位的id
既然說到建立連續欄位id,你會想到mysql的自增的主鍵id,其實有一點需要注意,如何為合適的列建立索引?當乙個事務開啟主鍵id+1,但是如果發生會滾,另外乙個事務再執行id會跳過那個回滾設定的主鍵,它認為這個id用了!
在where從句,order by從句,group by從句,on從句**現的列加索引,就是為常用的列新增索引。
建立的索引字段越小越好。索引欄位小了,每頁儲存的數量就多了,io就少了。
mysql中普遍選擇b+bree做索引,如果不太理解2,可以簡單了解一下b+tree原理。
建立聯合索引,兩方面考慮,一方面根據資料考慮,另一方面根據表字段訪問情況
對於下面的sql中where有兩個條件,此時建立兩個單個普通索引沒有用,所以要建立聯合索引。
select
*from payment where staff_id=
2and customer_id=
584;
選擇合適的資料型別
使用簡單的資料型別。int型在mysql中比varchar處理更簡單;
盡可能使用not null定義字段,null欄位mysql需要專門處理。
盡量少用text型別。
表的正規化化和反正規化化
正規化化是資料庫設計的規範,尤其是若不滿足第三正規化的表會存在以下問題:
反正規化化是指為了查詢效率的考慮把原本符合第三正規化的表適當的增加冗餘,以達到優化查詢的目的,反正規化化是一種以空間來換取時間的操作。
表的拆分
垂直拆分
所謂的垂直拆分就是把乙個擁有很多列的表拆分成多個表,解決寬度問題,通常按以下原則進行:
水平拆分
表的水平拆分是解決表資料量過大的問題,水平拆分每個表結構是一樣的。
水平拆分就是如何把資料均勻的分到水平拆分的每個表中。
比如 對id%表數量
作業系統配置優化
mysql資料庫優化
若涉及到這一步,就只能自己查閱資料來解決了,這裡就不細說了。
資料庫優化 資料庫設計優化
一 索引優化 1.首先索引不是越多越好,要視情況而定。因為索引會降低insert和update的效率 insert和update有時可能會重建索引。2.乙個表的索參數量最好不要超過6個,擇優而建。3.專案上線後,根據使用者的查詢條件字段稍微調整資料庫中的字段索引。二 分表 1.縱切 根據表字段來且分...
資料庫引擎優化顧問優化資料庫
現在一直在做的專案,資料量相對也不小,開始的時候沒有覺得,因為是剛開始,資料量還很小,在程式使用過程中速度還挺快,但是隨著資料量的不停的增長,發現程式越來越慢,甚至出現了超時的問題,因此要對程式和資料庫進行優化,前期專案比較緊,沒有針對大資料量業務進行分析設計,所以索引等相關優化沒有做到位,通過後期...
資料庫優化
資料庫優化 1 合理使用索引 索引是資料庫中重要的資料結構,它的根本目的就是提高查詢效率。索引的使用要恰到好處,其使用原則如下 在經常進行連線,但是沒有指定為外來鍵的列上建立索引,而不經常連線的字段則由優化器自動生成索引 在頻繁進行排序或分組 即進行groupby或orderby操作 的列上建立索引...