mysql的性能優化,提高查詢效率


1 商業需求對性能的影響
①不合理的需求
②無用功能堆積
 
比如需求:一個論壇貼子的總量統計
附加要求實時更新
count(*)比count(id)耗性能
並發請求壓力測試
使用冗余數據.
update鎖表時候select不能執行,mysql做的好,只鎖定幾行,但是還是存在這個select不能讀取的問題.
提交的請求失敗,會在下次重新提交.增加請求量.
解決辦法:判斷是不是真的需要實時更新.不做實時更新對性能有沒有影響,看不到精確的數據redis一秒接收10w次的更新
大數據翻頁
比如100w數據,一頁100個,得1W頁 所以一共寫一個100
 
2 mysql的執行流程
所有的查詢緩存sql,都遵循默認情況下,只要一個表的任何一條數據發生變化,查詢緩存都失效,
通過權限檢查之后,如果查詢緩存查不到數據,antlr(語法解析) 解析器解析語句,變成解析樹,
對樹進行預處理和優化,(常量,計算等等處理),查詢優化器(按照什么來查詢,mysql對數據的統計信息,索引,一共有多少數據,從多種查詢方案,根據mysql的統計信息去執行性能最快的執行方案)
sql的優化,是讓查詢優化器去執行程序員想讓其執行的方案去執行這個方案,步驟文檔傳遞給查詢執行引擎,調用對應的執行引擎,到磁盤上去找文件
查詢語句快慢根據i/o耗時,根據查詢計划來決定的,查詢計划根據解析樹,解析樹根據sql,如果開了查詢緩存,在客戶端顯示,查詢緩存存一份
優化sql,就是讓查詢優化器根據程序員的計划選擇匹配的計划,來減少i/o操作的時間
 
sql的優化原理:
①索引和索引的優化:
1索引的原理:把無序的數據變成有序的查詢
建立索引執行流程
1如果沒有索引,遍歷整張表再比較,全表掃描,i/o多
把表的內容按照索引列排序
1把數據按照某一列進行排序
2把排序的結果變成一個倒排表
 
②索引表的物理結構
1數據庫文件存儲的位置是在my.ini配置文件中,dataDir對能贏的數據目錄中
2每個數據庫一個文件夾
1mysam引擎:每個表一個table_name
table_name.MYL::索引信息和索引內容
TABLE_NAME.frm:存放的數據表的結構信息
table_name.myd:存放的數據表的內容
2innodb在:每一個表(table_name)
frm:存放的是數據表的結構信息
數據文件和索引文件都是統一存放在ibdata文件中
3索引文件都是額外存在的,對索引的查詢和維護
都是需要i/o的
 
③索引的結構(數據結構和算法基礎)
1默認情況下,一旦創建了一個表,還設置了主鍵
mysql會自動為這個主鍵創建一個unique的索引
2索引類型:
1 normal普通索引,允許一個索引值后面跟上多個行值,在一條鏈上
2unique:唯一索引,一個索引后面只能有一個行值,唯一約束也就是添加一個unique,當為一個表添加主鍵的時候,也就是為這個表的主鍵列添加了一個唯一索引
3fulltext:全文檢索,mysql的全文檢索只能使用mysam引擎,性能低,不建議使用
3索引的方法(規定索引的結構)
1  b+tree:
平衡樹:允許下面有很多子節點,但是整棵樹是平衡的
主鍵索引保存的是地址
其他是引用的主鍵的地址
btree中的詩句都是按照一定的順序保存的數據,是可以允許在
范圍內進行查詢
where *<100
2  hash
把索引的值做hash運算,並保存在hash表里面
優點:查詢單個,性能高
缺點:只能精確查詢,無法使用范圍查詢,沒有順序
如果大量的hash值相同,則性能較低
 
要想優化:從數據結構上想辦法
索引的利弊:
好處:1提高檢索效率
2排序列是索引列,如果查詢條件等於排序的列,並且做了索引)大大降低排序成本
3分組操作中,分組條件也是排序列,效率也高
問題:
索引需要額外的維護成本,因為其是單獨存在的,對數據增刪改都需要對索引進行額外操作,都會增加i/o
 
④怎么創建索引?
1查詢較頻繁的字段作為索引
2如果不能有效的區分數據,那么這個列就不適合作為索引
比如:accountTYPE 作為索引列,accountType只有14種
如果作為索引,只能按照1/14的比例過濾數據.
但是如果可能出現,只按照該條件查詢,考慮其他的性能提升的方式
select sum (amount )From accountflow Where accountType=0
第一種方案:單獨創建一個系統摘要表,建一個列較系統充值金額
第二種方案:使用增量查詢;
1創建一張表,記錄每一天的充值總金額(begindate,enddate,totalamount),每天使用
計時器對當天的充值記錄進行結算,記錄的都是截止昨天的數據
2創建一張月充值表,記錄一個月的充值總金額,每月最后一天進行結算.
3查詢總充值,從月報表中查詢當月之前匯總,從日充值中查詢當天之前截止時間的流水數據進匯總
使用另外一張當天流水表.記錄當天的流水,再把三個數據相加.
3更新非常頻繁的字段不適合做索引
索引有維護成本
4不會出現在where字句中的字段不應該創建索引
沒意義
5索引不是越多越好(只為必要的列創建索引)
①不管多少個索引,一次查詢一條sql只用一個索引
一個索引是一棵樹,索引和索引之間是獨立的
②因為索引和索引之間是獨立的,都是單獨維護的,數據的增刪改,
所有的索引都需要單獨改;
 
3 mysql中的索引的使用限制
1blpb和text類型的列只能創建前綴索引
2mysql目前不支持函數索引(在mysql中索引只能是一個列的原始值,不能把計算的值作為索引)
eg:查詢1981年入職的員工
select* from emp where year(hire_hade)='1981'
問題:經過函數的運算,就算作為索引,也不會使用索引
解決方案
1:select *from emp where hire_date between '1981-01-01' and '1981-12-31'
2:再創建一列,這列是year(hire_date)作為索引
3使用不等於無法使用索引
4join語句中on 兩邊的字段不一樣是無法用索引
5使用like如果以('%adc'),通配符開始無法用索引
1字符串可以用索引
2字符創創建的索引按照字母順序排序
a
ab
abb
baa
bab
3使用like,第一個為%或者_通配符,第一個字母無法識別排序
貨號 uq20160122222
查出2016的商品
6非等值查詢無法使用hash索引
 
單列索引和符合索引
1一位一個查詢至多只能使用一個索引,如果都是用單值索引
在數據量較大的情況下,不能很好地區分數據,
2mysql引入了多值索引(復合索引)
復合索引:多列的值組成的索引,多列的索引是有順序的;
3復合索引的原理: 類似orderby后面可以有多個排序條件
就是在排序和分組(創建倒排表)
select * from accountflow where action_time<'****' and accound_id =5
可以使用 action_time+accound_id的復合索引
select * from accountflow where action_time<'****'
可以使用 action_time+accound_id的復合索引
select * from accountflow where accound_id =5
不能使用action_time+accound_id的復合索引
select * from accountflow where accound_id =5 and action_time<'****' 不能使用action_time+accound_id的復合索引
4復合索引在查詢的時候,按照復合索引的順序依次查詢,不管查詢條件是不是完全
滿足所有的索引的列,都可以使用部分的復合索引,
5在實際應用中都是使用的復合索引
 
查看mysql的執行計划和執行明細狀態(explain profiling)
1 explain可以讓我們查看一條sql的執行計划
explain sql語句
type列:對表查詢所使用的方式
all:全表掃描
ref:使用索引查詢
key列 ;最終選折的索引
keylen列:鍵長
ref列:過濾方式
rows列:過濾查詢之后剩下的數據
extra列:查詢中每一步實現的細節
等值查詢優先於范圍查詢
 
join 優化:
 
小表連接大表,在小表中進行循環,減少內層循環
(用小的結果集去連大的結果集查詢)
保證join條件的字段作為索引
 
如果連接條件是a join b 哪個結果集小,哪個放前面,
在連接過程中,每連接一次 ,都會產生一個中間表,放在 join bufffer
 
sql 優化原則:
1選折需要優化的sql,不是所有的sql都需要優化,在優化的過程中,首選
更需要優化的sql
怎么選折?優先選折高並發低消耗的sql,
1 1小時請求10000次,1次10個i/o
2,1小時請求10次,1次10000個i/o
考慮:
1從單位時間產生的總數來說,是相同的
2針對一個sql,如果我能把10個i/o變成7個i/o
針對第二個sql,如果把1w變成7k個i/o
3從難度1w變成7000難得多
4從整體性能上來說.
如果並發太高,每一個慢一點點,就時間太大了,優化連接次數多的,對系統的影響就大一些.,先優化請求量大的
 
②定位性能的瓶頸
1sql運行較慢的有兩個影響原因,i/o和cpu
明確性能瓶頸所在
2明確優化目標,合理使用explain 和profile入手
1explain得到執行計划
2profile明確sql的問題和優化的結果
3小結果集驅動大結果集
4在索引中完成排序
5使用最小的columns
①減少網絡的傳輸數據量
②mysql的排序原理:
把所以胡的column數據全部取出,在排序u安存去排序,再返回結果,如果column數據量大,排序區容量不夠的時候,就會使用colum,n排序,再取數據,再返回多次請求方式,orderby 非常消耗性能
6 使用最有效的過濾條件
過多的where條件不一定能夠提高訪問性能,一定要讓where使用自己預期的執行計划
7避免復雜的join和子查詢
 
5 mysql主從:
①什么是mysql的組從,為什么要使用主從?
一個應用中大量消耗mysql的地方還是在查詢把mysql拆開,公路分路一樣.
 
配置主從的數據庫服務器:就算
1mysql拆成了多個,也必須分出主從所有的寫都在主的上面,
2所有的從都同步於主.
3既然涉及到同步就一定會有延遲
就可能在讀的時候產生臟數據,所以在從上面進行的讀操作,一定是對實時性和臟數據,有一定容忍度的數據,比如登錄日志,報表首頁,首頁統計信息來源文章咨詢,sns消息.
4在p2p中,做主從,大部分的讀操作 必須在主mysql上執行
(登錄日志,一審二審列表,用戶的流水信息,充值明細,投標明細,查詢類的業務可以定位到從mysql)
5注意:在mysql主從時,一個業務(service中的一個方法,如果
既有讀操作又有w操作,所以在一個事務中的所有的數據;資源只能來自於一個mysql)否則會出現臟數據的問題
 
②mysql主從原理
1要完成主從同步,就必須讓在master上執行的dml和ddl能夠在salve上,mysql選折使用文件來記錄sql
2主服務器上的bin-log記錄所有的dml和ddl+tcl操作
3mysql使用被動注冊的方式來讓那個從服務器請求同步主mysql的binlog:
4主從配置:
讀寫分離:
需求: 在后台的登錄日志中,讓登錄日志的查詢重數據庫中查詢,其他業務都還是使用主數據庫
 
1一個service方法必須要定位到一個唯一的數據庫上
mapper由sqlsessionfactory創建的,datasource創建的不同的方法對應不同的datasource
我們在程序中在方法中直接告訴應該去訪問哪個datasource
2引入路由datasource之后,在應用中,需要自己去確定(告訴路由這次要訪問的真實目標的datasource)
3讓路由ds知道有哪些真實的datasourc和它們的對應的名字
4讓路由知道我傳入的名字去返回真實的ds
 
 
 
 
 
 
 
 
 
 
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM