欧美free性护士vide0shd,老熟女,一区二区三区,久久久久夜夜夜精品国产,久久久久久综合网天天,欧美成人护士h版

首頁綜合 正文
目錄

柚子快報激活碼778899分享:MySQL 索引總結(jié)(2)

柚子快報激活碼778899分享:MySQL 索引總結(jié)(2)

http://yzkb.51969.com/

013 為什么官方建議使用自增長主鍵作為索引?(說一下自增主鍵和字符串類型主鍵的區(qū)別和影響)

自增主鍵能夠維持底層數(shù)據(jù)順序?qū)懭胱x取可以由b+樹的二分查找定位支持范圍查找,范圍數(shù)據(jù)自帶順序

字符串無法完成以上操作

014 使用int自增主鍵后 最大id是10,刪除id 10和9,再添加一條記錄,最后添加的id是幾?刪除后重啟mysql然后添加一條記錄最后id是幾?

刪除之后

如果重啟,會從最大的id開始遞增如果沒重啟,會延續(xù)刪除之前最大的id開始遞增

015 索引的優(yōu)缺點是什么?

優(yōu)點

聚簇(主鍵)索引:

順序讀寫范圍快速查找范圍查找自帶順序

非聚簇索引:

條件查詢避免全表掃描scan范圍,排序,分組查詢返回行id,排序分組后,再回表查詢完整數(shù)據(jù),有可能利用順序讀寫覆蓋索引不需要回表操作

索引的代價

索引是個好東西,可不能亂建,它在空間和時間上都會有消耗:

空間上的代價

每建立一個索引都要為它建立一棵B+樹,每一棵B+樹的每一個節(jié)點都是一個數(shù)據(jù)頁,一個頁默認會占用 16KB 的存儲空間,一棵很大的B+樹由許多數(shù)據(jù)頁組成,那就是很大的一片存儲空間。

時間上的代價

每次對表中的數(shù)據(jù)進行 增、刪、改 操作時,都需要去修改各個B+樹索引。而增、刪、改操作可能會對節(jié)點和記錄的排序造成破壞,所以存儲引擎需要額外的時間進行一些記錄移位、頁面分裂、頁面回收等操作來維護好節(jié)點和記錄的排序。如果我們建了許多索引,每個索引對應(yīng)的B+樹都要進行相關(guān)的維護操作,會給性能拖后腿。

B 樹和 B+ 樹都可以作為索引的數(shù)據(jù)結(jié)構(gòu),在 MySQL 中采用的是 B+ 樹。

但B樹和B+樹各有自己的應(yīng)用場景,不能說B+樹完全比B樹好,反之亦然。

016 使用索引一定能提升效率嗎?

不一定

少量數(shù)據(jù)全表掃描也很快,可以直接獲取到全量數(shù)據(jù)唯一索引會影響插入速度,但建議使用索引過多會影響更新,插入,刪除數(shù)據(jù)速度

017 如果是大段文本內(nèi)容,如何創(chuàng)建(優(yōu)化)索引?

B 樹和 B+ 樹都可以作為 索引的數(shù)據(jù)結(jié)構(gòu),**在 MySQL 中采用的是 B+ 樹。**

第一種方式是分表存儲,然后創(chuàng)建索引

第二是使用es為大文本創(chuàng)建索引

021 CRUD時聚簇索引與非聚簇索引的區(qū)別是什么?

聚簇索引插入新值比采用非聚簇索引插入新值的速度要慢很多,因為插入要保證主鍵不能重復(fù)聚簇索引范圍,排序查找效率高,因為是有序的非聚簇索引訪問需要兩次索引查找,第一次找到主鍵值,第二次根據(jù)主鍵值找到行數(shù)據(jù)

022 非聚簇索引為什么不存數(shù)據(jù)地址值而存儲主鍵?

因為聚簇索引中有時會引發(fā)分頁操作、重排操作數(shù)據(jù)有可能會移動

023 什么是回表操作?

id age name sex

age -> index

select * from user where age >20 ;

第一次 取回id,第二次(回表)根據(jù)id拿到完整數(shù)據(jù)

select * from user where age >20 ;

024 什么是覆蓋索引?

id age name sex

age -> index

select * from user where age >20 ;

第一次 取回id,第二次(回表)根據(jù)id拿到完整數(shù)據(jù)

age,name -> index

select age from user where age >20 and name like"張%" ;

覆蓋索引不會回表查詢,查詢效率也是比較高的

025 非聚集索引一定回表查詢嗎?

不一定,只要b+樹中包含的字段(創(chuàng)建索引的字段),覆蓋(包含)想要select 的字段,那么就不會回表查詢了。

026 為什么要回表查詢?直接存儲數(shù)據(jù)不可以嗎?

為了控制非聚簇索引的大小

027 如果把一個 InnoDB 表的主鍵刪掉,是不是就沒有主鍵,就沒辦法進行回表查詢了?

不是,InnoDB會生成rowid輔助回表查詢

028 什么是聯(lián)合索引,組合索引,復(fù)合索引?

為c2和c3列建立聯(lián)合索引,如下所示:

c2,c3 - > index

c3,c2 -> index

where c3=?

全職匹配

最左前綴

029 復(fù)合索引創(chuàng)建時字段順序不一樣使用效果一樣嗎?

我們也可以同時以多個列的大小作為排序規(guī)則,也就是同時為多個列建立索引,比方說我們想讓B+樹按照 c2和c3列 的大小進行排序,這個包含兩層含義:

先把各個記錄和頁按照c2列進行排序。在記錄的c2列相同的情況下,采用c3列進行排序B+樹葉子節(jié)點處的記錄由c2列、c3列和主鍵c1列組成本質(zhì)上也是二級索引

create index idx_c2_c3 on user (c2,c3);

030 什么是唯一索引?

隨表一起創(chuàng)建索引:

CREATE TABLE customer (

id INT UNSIGNED AUTO_INCREMENT,

customer_no VARCHAR(200),

customer_name VARCHAR(200),

PRIMARY KEY(id), -- 主鍵索引:列設(shè)定為主鍵后會自動建立索引,唯一且不能為空。

UNIQUE INDEX uk_no (customer_no), -- 唯一索引:索引列值必須唯一,允許有NULL值,且NULL可能會出現(xiàn)多次。

KEY idx_name (customer_name), -- 普通索引:既不是主鍵,列值也不需要唯一,單純的為了提高查詢速度而創(chuàng)建。

KEY idx_no_name (customer_no,customer_name) -- 復(fù)合索引:即一個索引包含多個列。

);

單獨建創(chuàng)索引:

CREATE TABLE customer1 (

id INT UNSIGNED,

customer_no VARCHAR(200),

customer_name VARCHAR(200)

);

ALTER TABLE customer1 ADD PRIMARY KEY customer1(id); -- 主鍵索引

CREATE UNIQUE INDEX uk_no ON customer1(customer_no); -- 唯一索引

CREATE INDEX idx_name ON customer1(customer_name); -- 普通索引

CREATE INDEX idx_no_name ON customer1(customer_no,customer_name); -- 復(fù)合索引

031 唯一索引是否影響性能?

032 什么時候使用唯一索引?

業(yè)務(wù)需求唯一字段的時候,一般不考慮性能問題

. 【強制】業(yè)務(wù)上具有唯一特性的字段,即使是多個字段的組合,也必須建成唯一索引。 說明:不要以為唯一索引影響了 insert 速度,這個速度損耗可以忽略,但提高查找速度是明 顯的;另外,即使在應(yīng)用層做了非常完善的校驗控制,只要沒有唯一索引,根據(jù)墨菲定律,必 然有臟數(shù)據(jù)產(chǎn)生。

033 什么時候適合創(chuàng)建索引,什么時候不適合創(chuàng)建索引?

適合創(chuàng)建索引

頻繁作為where條件語句查詢字段 關(guān)聯(lián)字段需要建立索引 排序字段可以建立索引 分組字段可以建立索引(因為分組前提是排序) 統(tǒng)計字段可以建立索引(如.count(),max())

不適合創(chuàng)建索引

頻繁更新的字段不適合建立索引 where,分組,排序中用不到的字段不必要建立索引 可以確定表數(shù)據(jù)非常少不需要建立索引 參與mysql函數(shù)計算的列不適合建索引

創(chuàng)建索引時避免有如下極端誤解:

1)寧濫勿缺。認為一個查詢就需要建一個索引。

2)寧缺勿濫。認為索引會消耗空間、嚴重拖慢更新和新增速度。

3)抵制惟一索引。認為業(yè)務(wù)的惟一性一律需要在應(yīng)用層通過“先查后插”方式解決。

034 什么是索引下推?

5.6之前的版本是沒有索引下推這個優(yōu)化的

**Using index condition:**叫作 Index Condition Pushdown Optimization (索引下推優(yōu)化)

如果沒有索引下推(ICP),那么MySQL在存儲引擎層找到滿足content1 > 'z'條件的第一條二級索引記錄。主鍵值進行回表,返回完整的記錄給server層,server層再判斷其他的搜索條件是否成立。如果成立則保留該記錄,否則跳過該記錄,然后向存儲引擎層要下一條記錄。如果使用了索引下推(ICP),那么MySQL在存儲引擎層找到滿足content1 > 'z'條件的第一條二級索引記錄。不著急執(zhí)行回表,而是在這條記錄上先判斷一下所有關(guān)于idx_content1索引中包含的條件是否成立,也就是content1 > 'z' AND content1 LIKE '%a'是否成立。如果這些條件不成立,則直接跳過該二級索引記錄,去找下一條二級索引記錄;如果這些條件成立,則執(zhí)行回表操作,返回完整的記錄給server層。

總結(jié):

未開啟索引下推:

根據(jù)篩選條件在索引樹中篩選第一個條件獲得結(jié)果集后回表操作進行其他條件篩選再次回表查詢

開啟索引下推:在條件查詢時,當前索引樹如果滿足全部篩選條件,可以在當前樹中完成全部篩選過濾,得到比較小的結(jié)果集再進行回表操作

035 有哪些情況會導致索引失效?

計算、函數(shù)導致索引失效

-- 顯示查詢分析

EXPLAIN SELECT * FROM emp WHERE emp.name LIKE 'abc%';

EXPLAIN SELECT * FROM emp WHERE LEFT(emp.name,3) = 'abc'; --索引失效

LIKE以%,_ 開頭索引失效

拓展:Alibaba《Java開發(fā)手冊》

【強制】頁面搜索嚴禁左模糊或者全模糊,如果需要請走搜索引擎來解決。

EXPLAIN SELECT * FROM emp WHERE name LIKE '%ab%'; --索引失效

不等于(!= 或者<>)索引失效

EXPLAIN SELECT SQL_NO_CACHE * FROM emp WHERE emp.name = 'abc' ;

EXPLAIN SELECT SQL_NO_CACHE * FROM emp WHERE emp.name <> 'abc' ; --索引失效

IS NOT NULL 失效 和 IS NULL

EXPLAIN SELECT * FROM emp WHERE emp.name IS NULL;

EXPLAIN SELECT * FROM emp WHERE emp.name IS NOT NULL; --索引失效

**注意:**當數(shù)據(jù)庫中的數(shù)據(jù)的索引列的NULL值達到比較高的比例的時候,即使在IS NOT NULL 的情況下 MySQL的查詢優(yōu)化器會選擇使用索引,此時type的值是range(范圍查詢)

-- 將 id>20000 的數(shù)據(jù)的 name 值改為 NULL

UPDATE emp SET `name` = NULL WHERE `id` > 20000;

-- 執(zhí)行查詢分析,可以發(fā)現(xiàn) IS NOT NULL 使用了索引

-- 具體多少條記錄的值為NULL可以使索引在IS NOT NULL的情況下生效,由查詢優(yōu)化器的算法決定

EXPLAIN SELECT * FROM emp WHERE emp.name IS NOT NULL

類型轉(zhuǎn)換導致索引失效

EXPLAIN SELECT * FROM emp WHERE name='123';

EXPLAIN SELECT * FROM emp WHERE name= 123; --索引失效

復(fù)合索引未用左列字段失效如果mysql覺得全表掃描更快時(數(shù)據(jù)少);

036 為什么LIKE以%開頭索引會失效?

id,name,age

name 創(chuàng)建索引

select * from user where name like ‘%明’

type=all

select name,id from user where name like ‘%明’

type=index

張明

(name,age)

其實并不會完全失效,覆蓋索引下會出現(xiàn)type=index,表示遍歷了索引樹,再回表查詢,

覆蓋索引沒有生效的時會直接type=all

沒有高效使用索引是因為字符串索引會逐個轉(zhuǎn)換成accii碼,生成b+樹時按首個字符串順序排序,類似復(fù)合索引未用左列字段失效一樣,跳過開始部分也就無法使用生成的b+樹了

037 一個表有多個索引的時候,能否手動選擇使用哪個索引?

不可用手動直接干預(yù),只能通過mysql優(yōu)化器自動選擇

038 如何查看一個表的索引?

show index from t_emp; // 顯示表上的索引

explain select * from t_emp where id=1; // 顯示可能會用到的索引及最終使用的索引

039 能否查看到索引選擇的邏輯?是否使用過optimizer_trace?

set session optimizer_trace="enabled=on",end_markers_in_json=on;

SELECT * FROM information_schema.OPTIMIZER_TRACE;

set session optimizer_trace="enabled=off";

040 多個索引優(yōu)先級是如何匹配的?

主鍵(唯一索引)匹配全值匹配(單值匹配)最左前綴匹配范圍匹配索引掃描全表掃描

一般性建議

? 對于單鍵索引,盡量選擇過濾性更好的索引(例如:手機號,郵件,身份證)

? 在選擇組合索引的時候,過濾性最好的字段在索引字段順序中,位置越靠前越好。

? 選擇組合索引時,盡量包含where中更多字段的索引

? 組合索引出現(xiàn)范圍查詢時,盡量把這個字段放在索引次序的最后面

? 盡量避免造成索引失效的情況

041 使用Order By時能否通過索引排序?

沒有過濾條件不走索引

042 通過索引排序內(nèi)部流程是什么?

select name,id from user where name like ‘%明’ order by name;

select name,id,age from user where name like ‘%明’

關(guān)鍵配置:

sort_buffer可供排序的內(nèi)存緩沖區(qū)大小max_length_for_sort_data 單行所有字段總和限制,超過這個大小啟動雙路排序

通過索引檢過濾篩選條件索到需要排序的字段+其他字段(如果是符合索引)判斷索引內(nèi)容是否覆蓋select的字段

如果覆蓋索引,select的字段和排序都在索引上,那么在內(nèi)存中進行排序,排序后輸出結(jié)果如果索引沒有覆蓋查詢字段,接下來計算select的字段是否超過max_length_for_sort_data限制,如果超過,啟動雙路排序,否則使用單路

043 什么是雙路排序和單路排序

單路排序:一次取出所有字段進行排序,內(nèi)存不夠用的時候會使用磁盤

雙路排序:取出排序字段進行排序,排序完成后再次回表查詢所需要的其他字段

如果不在索引列上,filesort有兩種算法: mysql就要啟動雙路排序和單路排序

雙路排序(慢)

Select id,age,name from stu order by name;

? MySQL 4.1之前是使用雙路排序,字面意思就是兩次掃描磁盤,最終得到數(shù)據(jù), 讀取行指針和order by列,對他們進行排序,然后掃描已經(jīng)排序好的列表,按照列表中的值重新從列表中讀取對應(yīng)的數(shù)據(jù)輸出

? 從磁盤取排序字段,在buffer進行排序,再從磁盤取其他字段。

? 取一批數(shù)據(jù),要對磁盤進行兩次掃描,眾所周知,I\O是很耗時的,所以在mysql4.1之后,出現(xiàn)了第二種改進的算法,就是單路排序。

單路排序(快)

從磁盤讀取查詢需要的所有列,按照order by列在buffer對它們進行排序,然后掃描排序后的列表進行輸出, 它的效率更快一些,避免了第二次讀取數(shù)據(jù)。并且把隨機IO變成了順序IO,但是它會使用更多的空間, 因為它把每一行都保存在內(nèi)存中了。

結(jié)論及引申出的問題

但是用單路有問題

在sort_buffer中,單路比多路要多占用很多空間,因為單路是把所有字段都取出, 所以有可能取出的數(shù)據(jù)的總大小超出了sort_buffer的容量,導致每次只能取sort_buffer容量大小的數(shù)據(jù),進行排序(創(chuàng)建tmp文件,多路合并),排完再取sort_buffer容量大小,再排……從而多次I/O。

單路本來想省一次I/O操作,反而導致了大量的I/O操作,反而得不償失。

優(yōu)化策略

? 增大sort_buffer_size參數(shù)的設(shè)置

? 增大max_length_for_sort_data參數(shù)的設(shè)置

? 減少select 后面的查詢的字段。 禁止使用select *

提高Order By的速度

\1. Order by時select * 是一個大忌。只Query需要的字段, 這點非常重要。在這里的影響是:

l 當Query的字段大小總和小于max_length_for_sort_data 而且排序字段不是 TEXT|BLOB 類型時,會用改進后的算法——單路排序, 否則用老算法——多路排序。

l 兩種算法的數(shù)據(jù)都有可能超出sort_buffer的容量,超出之后,會創(chuàng)建tmp文件進行合并排序,導致多次I/O,但是用單路排序算法的風險會更大一些,所以要提高sort_buffer_size。

\2. 嘗試提高 sort_buffer_size

l 不管用哪種算法,提高這個參數(shù)都會提高效率,當然,要根據(jù)系統(tǒng)的能力去提高,因為這個參數(shù)是針對每個進程(connection)的 1M-8M之間調(diào)整。 MySQL5.7和8.0,InnoDB存儲引擎默認值是1048576字節(jié),1MB。

SHOW VARIABLES LIKE ‘%sort_buffer_size%’;

?

\3. 嘗試提高 max_length_for_sort_data

l 提高這個參數(shù), 會增加用改進算法的概率。

SHOW VARIABLES LIKE ‘%max_length_for_sort_data%’;

#5.7默認1024字節(jié)

#8.0默認4096字節(jié)

l 但是如果設(shè)的太高,數(shù)據(jù)總?cè)萘砍鰏ort_buffer_size的概率就增大,明顯癥狀是高的磁盤I/O活動和低的處理器使用率。如果需要返回的列的總長度大于max_length_for_sort_data,使用雙路算法,否則使用單路算法。1024-8192字節(jié)之間調(diào)整

044 group by 分組和order by在索引使用上有什么區(qū)別?

group by 使用索引的原則幾乎跟order by一致 ,唯一區(qū)別:

group by 先排序再分組,遵照索引建的最佳左前綴法則group by沒有過濾條件,也可以用上索引。Order By 必須有過濾條件才能使用上索引。

045 如果表中有字段為null,又被經(jīng)常查詢該不該給這個字段創(chuàng)建索引?

應(yīng)該創(chuàng)建索引,使用的時候盡量使用is null判斷。

IS NOT NULL 失效 和 IS NULL

EXPLAIN SELECT * FROM emp WHERE emp.name IS NULL;

EXPLAIN SELECT * FROM emp WHERE emp.name IS NOT NULL; --索引失效

**注意:**當數(shù)據(jù)庫中的數(shù)據(jù)的索引列的NULL值達到比較高的比例的時候,即使在IS NOT NULL 的情況下 MySQL的查詢優(yōu)化器會選擇使用索引,此時type的值是range(范圍查詢)

-- 將 id>20000 的數(shù)據(jù)的 name 值改為 NULL

UPDATE emp SET `name` = NULL WHERE `id` > 20000;

-- 執(zhí)行查詢分析,可以發(fā)現(xiàn) IS NOT NULL 使用了索引

-- 具體多少條記錄的值為NULL可以使索引在IS NOT NULL的情況下生效,由查詢優(yōu)化器的算法決定

EXPLAIN SELECT * FROM emp WHERE emp.name IS NOT NULL

046 有字段為null索引是否會失效?

不一定會失效,每一條sql具體有沒有使用索引 可以通過trace追蹤一下

最好還是給上默認值

數(shù)字類型的給0,字符串給個空串“”,

柚子快報激活碼778899分享:MySQL 索引總結(jié)(2)

http://yzkb.51969.com/

相關(guān)鏈接

評論可見,查看隱藏內(nèi)容

本文內(nèi)容根據(jù)網(wǎng)絡(luò)資料整理,出于傳遞更多信息之目的,不代表金鑰匙跨境贊同其觀點和立場。

轉(zhuǎn)載請注明,如有侵權(quán),聯(lián)系刪除。

本文鏈接:http://gantiao.com.cn/post/19316333.html

發(fā)布評論

您暫未設(shè)置收款碼

請在主題配置——文章設(shè)置里上傳

掃描二維碼手機訪問

文章目錄