日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

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

生活随笔

當(dāng)前位置: 首頁(yè) > 运维知识 > 数据库 >内容正文

数据库

mysql范围条件_MySQL 索引及优化实战(一)

發(fā)布時(shí)間:2025/3/21 数据库 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 mysql范围条件_MySQL 索引及优化实战(一) 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

mysql

隨著系統(tǒng)用戶量的不斷增加,MySQL 索引的重要性不言而喻,對(duì)于后端工程師,只有在了解索引及其優(yōu)化的規(guī)則,并應(yīng)用于實(shí)際工作中后,才能不斷的提升系統(tǒng)性能,開(kāi)發(fā)出高性能、高并發(fā)和高可用的系統(tǒng)。

MySQL 索引及優(yōu)化實(shí)戰(zhàn)(一)和(二)會(huì)跟大家介紹一下 MySQL 索引中的各種概念,然后介紹優(yōu)化索引的若干條規(guī)則,最后利用這些規(guī)則,針對(duì)面試中??嫉闹R(shí)點(diǎn),做詳細(xì)的實(shí)例分析。通過(guò)這兩篇文章,您將學(xué)到如下內(nèi)容:

1. MySQL 索引概念:聚集索引、非聚集索引、聯(lián)合索引、主鍵、外鍵、唯一索引等。

2. MySQL 索引優(yōu)化規(guī)則:前導(dǎo)模糊查詢、or / in / union、負(fù)向查詢、null、最左前綴等。

3. 常見(jiàn)面試題分析:通過(guò)大量實(shí)例來(lái)說(shuō)明如何優(yōu)化索引。

索引概念和作用

索引是一種使記錄有序化的技術(shù),它可以指定按某列/某幾列預(yù)先排序,從而大大提高查詢速度(類(lèi)似于漢語(yǔ)詞典中按照拼音或者筆畫(huà)查找)。

索引的主要作用是加快數(shù)據(jù)查找速度,提高數(shù)據(jù)庫(kù)的性能。

MySQL 索引類(lèi)型

從物理存儲(chǔ)角度上,索引可以分為聚集索引和非聚集索引。

1.聚集索引(Clustered Index)

聚集索引決定數(shù)據(jù)在磁盤(pán)上的物理排序,一個(gè)表只能有一個(gè)聚集索引。

2.非聚集索引(Non-clustered Index)

非聚集索引并不決定數(shù)據(jù)在磁盤(pán)上的物理排序,索引上只包含被建立索引的數(shù)據(jù),以及一個(gè)行定位符 row-locator,這個(gè)行定位符,可以理解為一個(gè)聚集索引物理排序的指針,通過(guò)這個(gè)指針,可以找到行數(shù)據(jù)。

從邏輯角度,索引可以分為以下幾種。

1. 普通索引

最基本的索引,它沒(méi)有任何限制。

2. 唯一索引

與普通索引類(lèi)似,不同的就是索引列的值必須唯一,但允許有空值。如果是組合索引,則列值的組合必須唯一。

3. 主鍵索引

它是一種特殊的唯一索引,用于唯一標(biāo)識(shí)數(shù)據(jù)表中的某一條記錄,不允許有空值,一般用 primary key 來(lái)約束。主鍵和聚集索引的關(guān)系詳見(jiàn)“問(wèn)題詳解”中的第4題。

4. 聯(lián)合索引(又叫復(fù)合索引)

多個(gè)字段上建立的索引,能夠加速?gòu)?fù)合查詢條件的檢索。

5. 全文索引

老版本 MySQL 自帶的全文索引只能用于數(shù)據(jù)庫(kù)引擎為 MyISAM 的數(shù)據(jù)表,新版本 MySQL 5.6 的 InnoDB 支持全文索引。默認(rèn) MySQL 不支持中文全文檢索,可以通過(guò)擴(kuò)展 MySQL,添加中文全文檢索或?yàn)橹形膬?nèi)容表提供一個(gè)對(duì)應(yīng)的英文索引表的方式來(lái)支持中文。

MySQL索引優(yōu)化規(guī)則

可以通過(guò)以下規(guī)則對(duì) MySQL 索引進(jìn)行優(yōu)化。

1. 前導(dǎo)模糊查詢不能使用索引。

例如下面 SQL 語(yǔ)句不能使用索引。

select * from doc where title like '%XX'

而非前導(dǎo)模糊查詢則可以使用索引,如下面的 SQL 語(yǔ)句。

select * from doc where title like 'XX%'

頁(yè)面搜索嚴(yán)禁左模糊或者全模糊,如果需要可以用搜索引擎來(lái)解決。

2. union、in、or 都能夠命中索引,建議使用 in。

1)union:能夠命中索引。

示例代碼如下:

select * from doc where status=1union allselect * from doc where status=2

直接告訴 MySQL 怎么做,MySQL 耗費(fèi)的 CPU 最少,但是一般不這么寫(xiě) SQL。

2)in:能夠命中索引。

示例代碼如下:

select * from doc where status in (1, 2)

查詢優(yōu)化耗費(fèi)的 CPU 比 union all 多,但可以忽略不計(jì),一般情況下建議使用 in

3)or:新版的 MySQL 能夠命中索引。

示例代碼如下:

select * from doc where status = 1 or status = 2

查詢優(yōu)化耗費(fèi)的 CPU 比 in 多,不建議頻繁用 or。

3. 負(fù)向條件查詢不能使用索引,可以優(yōu)化為 in 查詢。

負(fù)向條件有:!=、<>、not in、not exists、not like 等。

例如下面代碼:

select * from doc where status != 1 and status != 2

可以優(yōu)化為 in 查詢:

select * from doc where status in (0,3,4)

4.聯(lián)合索引最左前綴原則(又叫最左側(cè)查詢)

1)如果在(a,b,c)三個(gè)字段上建立聯(lián)合索引,那么它能夠加快 a | (a,b) | (a,b,c) 三組查詢速度。

例如登錄業(yè)務(wù)需求,代碼如下。

select uid, login_time from user where login_name=? and passwd=?

可以建立(login_name, passwd)的聯(lián)合索引。

因?yàn)闃I(yè)務(wù)上幾乎沒(méi)有 passwd 的單條件查詢需求,而有很多 login_name 的單條件查詢需求,所以可以建立(login_name, passwd)的聯(lián)合索引,而不是(passwd, login_name)。

2)建聯(lián)合索引的時(shí)候,區(qū)分度最高的字段在最左邊。

3)如果建立了(a,b)聯(lián)合索引,就不必再單獨(dú)建立 a 索引。同理,如果建立了(a,b,c)聯(lián)合索引,就不必再單獨(dú)建立 a、(a,b) 索引。

4)存在非等號(hào)和等號(hào)混合判斷條件時(shí),在建索引時(shí),請(qǐng)把等號(hào)條件的列前置。如 where a>? and b=?,那么即使 a 的區(qū)分度更高,也必須把 b 放在索引的最前列。

5)最左側(cè)查詢需求,并不是指 SQL 語(yǔ)句的 where 順序要和聯(lián)合索引一致。

下面的 SQL 語(yǔ)句也可以命中 (login_name, passwd) 這個(gè)聯(lián)合索引。

select uid, login_time from user where passwd=? and login_name=?

但還是建議 where 后的順序和聯(lián)合索引一致,養(yǎng)成好習(xí)慣。

5. 范圍列可以用到索引(聯(lián)合索引必須是最左前綴)。

1)范圍條件有:、>=、between等。

2)范圍列可以用到索引(聯(lián)合索引必須是最左前綴),但是范圍列后面的列無(wú)法用到索引,索引最多用于一個(gè)范圍列,如果查詢條件中有兩個(gè)范圍列則無(wú)法全用到索引。

假如有聯(lián)合索引 (empno、title、fromdate),那么下面的 SQL 中 emp_no 可以用到索引,而 title 和 from_date 則使用不到索引。

select * from employees.titles where emp_no < 10010' and and from_date between '1986-01-01' and '1986-12-31'

6. 把計(jì)算放到業(yè)務(wù)層而不是數(shù)據(jù)庫(kù)層。

1)在字段上進(jìn)行計(jì)算不能命中索引。

例如下面的 SQL 語(yǔ)句。

select * from doc where YEAR(create_time) <= '2016'

即使 date 上建立了索引,也會(huì)全表掃描,可優(yōu)化為值計(jì)算,如下:

select * from doc where create_time <= '2016-01-01'

2)把計(jì)算放到業(yè)務(wù)層。

這樣做不僅可以節(jié)省數(shù)據(jù)庫(kù)的 CPU,還可以起到查詢緩存優(yōu)化效果。

比如下面的 SQL 語(yǔ)句:

select * from order where date < = CURDATE()

可以優(yōu)化為:

select * from order where date < = '2018-01-24 12:00:00'

優(yōu)化后的 SQL 釋放了數(shù)據(jù)庫(kù)的 CPU 多次調(diào)用,傳入的 SQL 相同,才可以利用查詢緩存。7. 強(qiáng)制類(lèi)型轉(zhuǎn)換會(huì)全表掃描

如果 phone 字段是 varchar 類(lèi)型,則下面的 SQL 不能命中索引。

select * from user where phone=13800001234

可以優(yōu)化為:

select * from user where phone='13800001234'

8. 更新十分頻繁、數(shù)據(jù)區(qū)分度不高的字段上不宜建立索引。

1)更新會(huì)變更 B+ 樹(shù),更新頻繁的字段建立索引會(huì)大大降低數(shù)據(jù)庫(kù)性能。

2)“性別”這種區(qū)分度不大的屬性,建立索引是沒(méi)有什么意義的,不能有效過(guò)濾數(shù)據(jù),性能與全表掃描類(lèi)似。

3)一般區(qū)分度在80%以上的時(shí)候就可以建立索引,區(qū)分度可以使用 count(distinct(列名))/count(*) 來(lái)計(jì)算。

9. 利用覆蓋索引來(lái)進(jìn)行查詢操作,避免回表。

被查詢的列,數(shù)據(jù)能從索引中取得,而不用通過(guò)行定位符 row-locator 再到 row 上獲取,即“被查詢列要被所建的索引覆蓋”,這能夠加速查詢速度。

例如登錄業(yè)務(wù)需求,代碼如下。

select uid, login_time from user where login_name=? and passwd=?

可以建立(login_name, passwd, login_time)的聯(lián)合索引,由于 login_time 已經(jīng)建立在索引中了,被查詢的 uid 和 login_time 就不用去 row 上獲取數(shù)據(jù)了,從而加速查詢。

10. 如果有 order by、group by 的場(chǎng)景,請(qǐng)注意利用索引的有序性。

1)order by 最后的字段是組合索引的一部分,并且放在索引組合順序的最后,避免出現(xiàn) file_sort 的情況,影響查詢性能。

2)例如對(duì)于語(yǔ)句 where a=? and b=? order by c,可以建立聯(lián)合索引(a,b,c)。

3)如果索引中有范圍查找,那么索引有序性無(wú)法利用,如 WHERE a>10 ORDER BY b;,索引(a,b)無(wú)法排序。

這篇文章介紹了MySQL索引的概念及10條優(yōu)化規(guī)則,下篇文章會(huì)介紹第11~20條優(yōu)化規(guī)則,并通過(guò)實(shí)例來(lái)驗(yàn)證這些規(guī)則。

總結(jié)

以上是生活随笔為你收集整理的mysql范围条件_MySQL 索引及优化实战(一)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

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