日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) >

对mysql优化关注_MySQL优化看这篇就对了

發(fā)布時(shí)間:2024/9/19 45 豆豆
生活随笔 收集整理的這篇文章主要介紹了 对mysql优化关注_MySQL优化看这篇就对了 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

我們?cè)诿嬖嚨臅r(shí)候經(jīng)常被問(wèn)到你如何對(duì)數(shù)據(jù)庫(kù)優(yōu)化?動(dòng)不動(dòng)就分庫(kù)分表,但是實(shí)際上有幾個(gè)有分庫(kù)分表的經(jīng)驗(yàn)?zāi)?#xff1f;下面我們將介紹優(yōu)化數(shù)據(jù)庫(kù)的各個(gè)階段。

一、SQL語(yǔ)句優(yōu)化

sql語(yǔ)句的優(yōu)化是我們優(yōu)化數(shù)據(jù)庫(kù)的第一個(gè)階段,也是要最先考慮的方案,成本最低,見(jiàn)效最快的方案。

1.通過(guò)慢查詢(xún)?nèi)罩?#xff0c;找到我們的慢sql

2.通過(guò)EXPLAIN分析執(zhí)行計(jì)劃,使用索引。

慢查詢(xún)?nèi)罩鹃_(kāi)啟

vim /etc/my.cnf

加入如下三行:

slow_query_log=ON //開(kāi)啟慢查詢(xún)

slow_query_log_file=/var/lib/mysql/slow.log //慢查詢(xún)?nèi)罩疚恢?/p>

long_query_time=3 //達(dá)到多少秒的sql就記錄日志,這里是3s

//重啟

systemctl restart mysqld;

執(zhí)行計(jì)劃分析

[圖片上傳失敗...(image-5181eb-1586497621890)]

id:值越大越先執(zhí)行,id相同,從上到下執(zhí)行

key:使用的索引,為空就是不使用

type:

? all:全表掃描

? index:索引全掃描,MySQL遍歷掙個(gè)索引來(lái)查詢(xún)匹配的行,跟all相比就差了個(gè)排序,因?yàn)樗饕緛?lái)就是有序的

? range:索引范圍掃描,常見(jiàn)于、>=、between等操作符

? ref:使用非唯一索引或唯一索引的前綴掃描,返回匹配的單行數(shù)據(jù),這個(gè)就是我們平時(shí)理解的索引查詢(xún)方式B+樹(shù)二分法查詢(xún)

? eq_ref:類(lèi)似ref,區(qū)別就在于使用的索引是唯一索引,簡(jiǎn)單來(lái)說(shuō),就是多表連接中使用primary key或者unique index作為關(guān)聯(lián)條件。

? const/system:單表中最多有一個(gè)匹配行,查詢(xún)起來(lái)非常迅速,常見(jiàn)于根據(jù)primary key或者唯一索引unique index進(jìn)行的單表查詢(xún)

? null:mysql不用訪問(wèn)表或者索引,直接就能夠得到查詢(xún)的結(jié)果,例如select 1+2 as result。

Extra:執(zhí)行情況的說(shuō)明和描述,包含不適合在其他列中顯示但是對(duì)執(zhí)行計(jì)劃非常重要的額外信息,常用取值如下:

? Using index:直接訪問(wèn)索引就取到了數(shù)據(jù),高性能的表現(xiàn)。

? Using where:直接在主鍵索引上過(guò)濾數(shù)據(jù),必帶where子句,而且用不上索引

? Using index condition:先條件過(guò)濾索引,再查數(shù)據(jù),

? Using filesort:使用了外部文件排序 只要見(jiàn)到這個(gè) 就要優(yōu)化掉

? Using temporary:創(chuàng)建了臨時(shí)表來(lái)處理查詢(xún) 只要見(jiàn)到這個(gè) 也要盡量?jī)?yōu)化掉

SQL執(zhí)行順序

[圖片上傳失敗...(image-eec99-1586497621891)]

不是絕對(duì)的有時(shí)候,優(yōu)化器也會(huì)執(zhí)行where過(guò)濾些數(shù)據(jù)在join

優(yōu)化爭(zhēng)議無(wú)數(shù)的count()

count(1)、count()、count(列)在innodb引擎中

? count(1)和count()直接就是統(tǒng)計(jì)主鍵,他們兩個(gè)的效率是一樣的。如果刪除主鍵,他們都走全表掃描。

? 如果count(列)中的字段是索引的話,count(列)和count()一樣快,否則count(列)走全表掃描。

MyiSAM引擎的count(*),因?yàn)镸yiSAM有記錄當(dāng)前的總行數(shù),所以直接取該值就行,快得一逼,但是這個(gè)要在沒(méi)有where條件的情況下,當(dāng)統(tǒng)計(jì)帶有where條件的查詢(xún),那么mysql的count()和其他存儲(chǔ)引擎就沒(méi)有什么不同了

優(yōu)化filesort

當(dāng)我們使用order by進(jìn)行排序的時(shí)候可能會(huì)出現(xiàn)Using filesort,這個(gè)時(shí)候我們就要將這個(gè)優(yōu)化掉

mysql排序方式有2種

? 直接通過(guò)有序索引返回?cái)?shù)據(jù),這種方式的extra顯示為Using Index,不需要額外的排序,操作效率較高。

? 對(duì)返回的數(shù)據(jù)進(jìn)行排序,也就是通常看到的Using filesort,filesort是通過(guò)相應(yīng)的排序算法,將數(shù)據(jù)放在sort_buffer_size系統(tǒng)變量設(shè)置的內(nèi)存排序區(qū)中進(jìn)行排序,如果內(nèi)存裝載不下,它就會(huì)將磁盤(pán)上的數(shù)據(jù)進(jìn)行分塊,再對(duì)各個(gè)數(shù)據(jù)塊進(jìn)行排序,然后將各個(gè)塊合并成有序的結(jié)果集。

SELECT * FROM DB.TB WHERE ID=2222 AND FID IN (9,8,3,13,38,40) ORDER BY INVERSE_DATE LIMIT 0, 5

建立一個(gè)索引 IDX(ID,FID ,INVERSE_DATE)這個(gè)時(shí)候就會(huì)出現(xiàn)Using where; Using filesort。

因?yàn)榻⑺饕臅r(shí)候是id排序后,id相同再排FID,當(dāng)FID有序后,當(dāng)FID相同在排INVERSE_DATE。

這里id是固定,所以我們重新建立一個(gè)索引(ID,INVERSE_DATE),這樣就不會(huì)出現(xiàn)Using filesort。

優(yōu)化limit 分頁(yè)

select * from product limit 10, 20 0.016秒

select * from product limit 100, 20 0.016秒

select * from product limit 1000, 20 0.047秒

select * from product limit 10000, 20 0.094秒

select * from product limit 400000, 20 3.229秒

可以看到隨著條數(shù)的增加,時(shí)間增長(zhǎng)

一般優(yōu)化這個(gè)有兩種

SELECT * FROM product WHERE ID > =(select id from product limit 866613, 1) limit 20 0.2秒

SELECT * FROM product a JOIN (select id from product limit 866613, 20) b ON a.ID = b.id

加一個(gè)參數(shù)來(lái)輔助,標(biāo)記分頁(yè)的開(kāi)始位置:可以是上一次分頁(yè)最大時(shí)間等,這里用id

SELECT * FROM product WHERE id > 800000 LIMIT 20

帶有where的語(yǔ)句

select id from collect where vtype=1 limit 1000,10;

索引應(yīng)該這樣建立(vtype,id),不要建成(id,vtype)

優(yōu)化子查詢(xún)

常見(jiàn)的優(yōu)化方式

? join的時(shí)候使用小表作為主表,驅(qū)動(dòng)表。

select * from a join b on a.id=b.aid where a.create_time>xxx and b.create_time>xxxx

當(dāng)a根據(jù)創(chuàng)建時(shí)間過(guò)濾后的條數(shù)和b根據(jù)過(guò)濾時(shí)間的條數(shù),做比較。。不是直接a,b表做比較

? 不要在列上做運(yùn)算where a-10 = 20 這樣不使用索引,換成 where a=20+10

? 類(lèi)型要一樣 where a=123 如果a是varchar類(lèi)型,這樣就不會(huì)使用索引 換成 where a=‘123’

? IN適合于外表大而內(nèi)表小的情況;EXISTS適合于外表小而內(nèi)表大的情況,這樣效率會(huì)高的

? 能夠用BETWEEN的就不要用IN

? 能夠用DISTINCT的就不用GROUP BY

? 避免使用!=或<>、IS NULL或IS NOT NULL、IN ,NOT IN等這樣的操作符.

? select 列,使用覆蓋索引,減少回表查詢(xún).

一張表最多只存多少數(shù)據(jù),為什么使用B+樹(shù),不使用B樹(shù)

深入理解mysql B+樹(shù)

優(yōu)化器選擇不使用索引

SELECT creator_name,run_time FROM oa_crm_log ORDER BY creator_name limit 10

[圖片上傳失敗...(image-292c4a-1586497621891)]

SELECT creator_name,run_time FROM oa_crm_log ORDER BY creator_name limit 10000

[圖片上傳失敗...(image-7e0c4-1586497621891)]

第一條使用了索引,第二條沒(méi)有使用索引。為什么呢?

這第二條是因?yàn)槲覀冞@個(gè)是非聚集索引,掃描完索引之后還需要,根據(jù)id去隨機(jī)讀取磁盤(pán)(10000次)

而隨機(jī)讀取的性能是很差的。所以sql優(yōu)化器判斷之后使用全表掃描(順序讀取磁盤(pán)性能還是高的)

第一條雖然也是這樣,但是只需要查詢(xún)10條隨機(jī)讀取磁盤(pán)的次數(shù)(10次),相對(duì)比較少,所以sql優(yōu)化器判斷之后使用了索引

優(yōu)化:我們可以使用覆蓋索引,讓我們b+樹(shù)的索引存儲(chǔ)了索引key,這樣我們就不用在回表去查詢(xún)了

建立(creator_name,run_time)的聯(lián)合索引

滿(mǎn)足了使用索引的原則,mysql還是可能會(huì)棄用索引,因?yàn)橛行┎樵?xún)即使使用索引,也會(huì)出現(xiàn)大量的隨機(jī)io,相對(duì)于從數(shù)據(jù)記錄中的順序io開(kāi)銷(xiāo)更大。

join原理 NLJ、BNL、MRR、BKA

顛覆最左原則

t_article表 索引 idnex001(creator_id,updator_id,upator)

select * from t_article where updator_id = 1

select updator_id from t_article where updator_id = 1

這兩條sql會(huì)使用索引嗎?根據(jù)我們理解的mysql最左原則,兩條sql都不會(huì)使用索引。但是事實(shí)卻不是。

第一條,不是使用索引

[圖片上傳失敗...(image-3242e0-1586497621891)]

第二條使用type 為index的索引

[圖片上傳失敗...(image-5d10b6-1586497621891)]

index:這種類(lèi)型表示是mysql會(huì)對(duì)整個(gè)該索引進(jìn)行掃描。要想用到這種類(lèi)型的索引,對(duì)這個(gè)索引并無(wú)特別要求,只要是索引,或者某個(gè)復(fù)合索引的一部分,mysql都可能會(huì)采用index類(lèi)型的方式掃描。但是呢,缺點(diǎn)是效率不高,mysql會(huì)從索引中的第一個(gè)數(shù)據(jù)一個(gè)個(gè)的查找到最后一個(gè)數(shù)據(jù),直到找到符合判斷條件的某個(gè)索引。

所以上面兩條都滿(mǎn)足使用index的原則。

第一條沒(méi)有使用索引是因?yàn)槲覀儾樵?xún)select * 的話,輔助索引還需要到主鍵索引進(jìn)行隨機(jī)查詢(xún)。。優(yōu)化器認(rèn)為順序掃描更優(yōu),所以沒(méi)有使用索引

第二條就不需要在要主鍵索引進(jìn)行隨機(jī)查詢(xún),所以使用了index類(lèi)型的索引。

mysql 聚簇與非聚簇索引

二、引入緩存

在sql優(yōu)化搞不定的時(shí)候,我們才需要考慮引入緩存,但我們要知道當(dāng)引入緩存的時(shí)候系統(tǒng)的復(fù)雜性增加了,同時(shí)也會(huì)引入很多問(wèn)題,比如數(shù)據(jù)庫(kù)和緩存一致性問(wèn)題等等。

這里很多問(wèn)題都寫(xiě)過(guò)了。。參照下面各個(gè)鏈接

mybatis的二級(jí)緩存、ehcache本地緩存

這個(gè)比較簡(jiǎn)單省略

redis的分布式緩存

Redis安裝及持久化

數(shù)據(jù)庫(kù)和緩存不一致的方案

刪除緩存還是更新緩存

先操作緩存(刪除緩存)還是數(shù)據(jù)庫(kù)

緩存穿透、擊穿、雪崩

緩存重建沖突(分布式鎖)、使用雙層nginx提高緩存命中

三、讀寫(xiě)分離

數(shù)據(jù)庫(kù)主從不一致

從庫(kù)和緩存不一致(雙淘汰方案)

四、分區(qū)表

五、垂直拆分

六、水平拆分

總結(jié)

以上是生活随笔為你收集整理的对mysql优化关注_MySQL优化看这篇就对了的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。