MySQL添加索引及添加字段并建立索引方式
MySQL添加索引及字段并建立索引
添加字段并設(shè)置字段主鍵
alter table table_name drop primary key; alter table table_name add column column2 varchar(10) NOT NULL COMMENT 'column2' AFTER column2; alter table table_name add constraint user_test primary key(column_list);
新建索引
使用CREATE語句創(chuàng)建索引:
- 普通索引:
CREATE INDEX index_name ON table_name(column_name1,column_name2);
- 唯一索引:
CREATE UNIQUE INDEX index_name ON table_name(column_name);
- 主鍵索引:
CREATE PRIMARY KEY INDEX index_name ON table_name(column_name);
使用ALTER TABLE語句創(chuàng)建索引:
- 普通索引:
alter table table_name add index index_name (column_list);
- 唯一索引:
alter table table_name add unique index_name (column_list);
- 主鍵索引:
alter table table_name add primary key (column_list);
- 全文索引:
alter table table_name add fulltext index_name (column_list);
該語句指定了索引為 fulltext。
刪除索引
drop index index_name on table_name; alter table table_name drop index index_name; alter table table_name drop primary key;
修改
- MySQL 5.7以上:
alter table table_name rename index old_index_name to new_index_name;
- MySQL 5.7之前:
alter table table_name drop index old_index_name alter table table_name add index new_index_name(column_list)
查詢
使用 show index 命令來列出表中的相關(guān)的索引信息。
可以通過添加 \g 來格式化輸出信息。
show index from table_name \g
MySQL索引介紹及使用
MySQL索引介紹
1. 概念
MySQL官方對索引的定義為:索引(Index)是幫助MySQL高效獲取數(shù)據(jù)的數(shù)據(jù)結(jié)構(gòu)??梢缘玫剿饕谋举|(zhì):索引是排好序的快速查找數(shù)據(jù)結(jié)構(gòu)。一般來說索引本身也很大,不可能全部存儲在內(nèi)存中,因此索引往往以索引文件的形式存儲在磁盤上。
2.優(yōu)勢
- 所有的MySql列類型(字段類型)都可以被索引,也就是可以給任意字段設(shè)置索引。
- 大大加快數(shù)據(jù)的查詢速度。
- 提高數(shù)據(jù)檢索的效率,降低數(shù)據(jù)排序的成本
3.劣勢
- 實際上索引也是一張表,該表保存了主鍵與索引字段,并指向?qū)嶓w表的記錄,所以索引列也是要占用空間的。
- 雖然索引大大提高了查詢速度,同時卻會降低更新表的速度,如對表進(jìn)行INSERT、UPDATE和DELETE。因為更新表時,MySQL不僅要保存數(shù)據(jù),還要保存一下索引文件每次更新添加了索引列的字段,都會調(diào)整因為更新所帶來的鍵值變化后的索引信息。
- 索引只是提高效率的一個因素,如果你的MySQL有大數(shù)據(jù)量的表,就需要花時間研究建立最優(yōu)秀的索引,或者優(yōu)化查詢。
4.使用原則
- 對經(jīng)常更新的表就避免對其設(shè)置過多的索引,對經(jīng)常用于查詢的字段應(yīng)該創(chuàng)建索引。
- 數(shù)據(jù)量小的表最好不要使用索引,因為由于數(shù)據(jù)較少,可能查詢?nèi)繑?shù)據(jù)花費的時間比遍歷索引的時間還要短,索引就可能不會產(chǎn)生優(yōu)化效果。
- 在一個列上(字段上)不同值較少的不要建立索引,比如在學(xué)生表的"性別"字段上只有男,女兩個不同值。相反的,在一個字段上不同值較多的可是建立索引。
5. mysql索引結(jié)構(gòu)
- B+樹索引
- Hash索引
- full-text全文索引
- R-Tree索引
6. 哪些情況需要創(chuàng)建索引
- 主鍵自動建立唯一索引
- 頻繁作為查詢條件的字段應(yīng)該創(chuàng)建索引
- 查詢中與其它表關(guān)聯(lián)的字段,外鍵關(guān)系建立索引
- 頻繁更新的字段不適合創(chuàng)建索引,因為每次更新不單單是更新了記錄,還會更新索引,加重IO負(fù)擔(dān)
- where條件里用不到的字段不創(chuàng)建索引
- 單鍵/組合索引的選擇問題,who?(在高并發(fā)下傾向創(chuàng)建組合索引)
- 查詢中排序的字段,排序字段若通過索引去訪問將大大提高排序速度
- 查詢中統(tǒng)計或者分組字段
7. 哪些情況不需要創(chuàng)建索引
- 表記錄太少
- 經(jīng)常增刪改的表:雖然提高了查詢速度,同時卻會降低更新表的速度,如對表進(jìn)行INSERT、UPDATE和DELETE。因為更新表時,MySQL不僅要保存數(shù)據(jù),還要保存一下索引文件。
- 數(shù)據(jù)重復(fù)且分布平均的表字段,因此應(yīng)該只為最經(jīng)常查詢和最經(jīng)常排序的數(shù)據(jù)列建立索引。注意,如果某個數(shù)據(jù)列包含許多重復(fù)的內(nèi)容,為它建立索引就沒有太大的實際效果。
8. 創(chuàng)建索引的語句
CREATE TABLE table_name[col_name data type] [unique|fulltext][index|key][index_name](col_name[length])[asc|desc]
- unique|fulltext為可選參數(shù),分別表示唯一索引、全文索引
- index和key為同義詞,兩者作用相同,用來指定創(chuàng)建索引
- col_name為需要創(chuàng)建索引的字段列,該列必須從數(shù)據(jù)表中該定義的多個列中選擇
- index_name指定索引的名稱,為可選參數(shù),如果不指定,默認(rèn)col_name為索引值
- length為可選參數(shù),表示索引的長度,只有字符串類型的字段才能指定索引長度
- asc或desc指定升序或降序的索引值存儲
9. 刪除索引的語句
DROP INDEX 索引名 ON 表名; ## 刪除book表中的名稱為BkNameIdx的索引 DROP INDEX BkNameIdx ON book;
10. 查看表的索引
## 查看表的索引 SHOW INDEX FROM book;
mysql索引分類及使用
MySQL中分為:普通索引,唯一索引,主鍵索引,組合索引,和全文索引。
1. 普通索引
是最基本的索引,它沒有任何限制,允許在定義索引的列中插入重復(fù)值和空值,純粹為了查詢數(shù)據(jù)更快一點。。
它有以下幾種創(chuàng)建方式:
# 1.直接創(chuàng)建索引 CREATE INDEX index_name ON table(column(length)) # 2.修改表結(jié)構(gòu)的方式添加索引 ALTER TABLE table_name ADD INDEX index_name ON (column(length)) # 3.創(chuàng)建表的時候同時創(chuàng)建索引 CREATE TABLE `table` ( `id` int(11) NOT NULL AUTO_INCREMENT , `title` char(255) CHARACTER NOT NULL , `content` text CHARACTER NULL , `time` int(10) NULL DEFAULT NULL , PRIMARY KEY (`id`), INDEX index_name (title(length)) ) # 4.刪除索引 DROP INDEX index_name ON table
2. 唯一索引
與前面的普通索引類似,不同的就是:索引列的值必須唯一,但允許有空值。如果是組合索引,則列值的組合必須唯一。
它有以下幾種創(chuàng)建方式:
# 1.創(chuàng)建唯一索引 CREATE UNIQUE INDEX indexName ON table(column(length)) # 2.修改表結(jié)構(gòu) ALTER TABLE table_name ADD UNIQUE indexName ON (column(length)) # 3.創(chuàng)建表的時候直接指定 CREATE TABLE `table` ( `id` int(11) NOT NULL AUTO_INCREMENT , `title` char(255) CHARACTER NOT NULL , `content` text CHARACTER NULL , `time` int(10) NULL DEFAULT NULL , UNIQUE indexName (title(length)) );
3. 主鍵索引
是一種特殊的唯一索引,一個表只能有一個主鍵,不允許有空值。
一般是在建表的時候同時創(chuàng)建主鍵索引:
CREATE TABLE `table` ( `id` int(11) NOT NULL AUTO_INCREMENT , `title` char(255) NOT NULL , PRIMARY KEY (`id`) );
4. 組合索引
指多個字段上創(chuàng)建的索引,只有在查詢條件中使用了創(chuàng)建索引時的第一個字段,索引才會被使用。
使用組合索引時遵循最左前綴集合
#添加組合索引 ALTER TABLE `table` ADD INDEX name_city_age (id,name,age); #創(chuàng)建組合索引 CREATE TABLE tab3( id INT(4) NOT NULL, name CHAR(20) NOT NULL, age INT(3) NOT NULL, info VARCHAR(255), INDEX multiIdx(id,name,age) );
最左前綴:組合索引遵從了最左前綴,利用索引中最左邊的列集來匹配行,這樣的列集稱為最左前綴。例如,這里由id、name和age3個字段構(gòu)成的索引,索引行中就按id/name/age的順序存放,索引組合中的字段可以是(id,name,age)、(id,name)或者(id)。如果要查詢的字段不構(gòu)成最左面的前綴原則,那么就不會用索引,比如,age或者(name,age)組合就不會使用索引查詢。
5. 全文索引
主要用來查找文本中的關(guān)鍵字,而不是直接與索引中的值相比較。
fulltext索引跟其它索引大不相同,它更像是一個搜索引擎,而不是簡單的where語句的參數(shù)匹配。
fulltext索引配合match against操作使用,而不是一般的where語句加like。
它可以在create table,alter table ,create index使用,不過目前只有char、varchar,text 列上可以創(chuàng)建全文索引。
值得一提的是,在數(shù)據(jù)量較大時候,現(xiàn)將數(shù)據(jù)放入一個沒有全局索引的表中,然后再用CREATE index創(chuàng)建fulltext索引,要比先為一張表建立fulltext然后再將數(shù)據(jù)寫入的速度快很多。
# 1.創(chuàng)建表的適合添加全文索引 CREATE TABLE `table` ( `id` int(11) NOT NULL AUTO_INCREMENT , `title` char(255) CHARACTER NOT NULL , `content` text CHARACTER NULL , `time` int(10) NULL DEFAULT NULL , PRIMARY KEY (`id`), FULLTEXT (content) ); # 2.修改表結(jié)構(gòu)添加全文索引 ALTER TABLE article ADD FULLTEXT index_content(content) # 3.直接創(chuàng)建索引 CREATE FULLTEXT INDEX index_content ON article(content)
Explain
1. 概念
Explain(查看執(zhí)行計劃),使用EXPLAIN關(guān)鍵字可以模擬優(yōu)化器執(zhí)行SQL查詢語句,從而知道MySQL是如何處理你的SQL語句的。
分析你的查詢語句或是表結(jié)構(gòu)的性能瓶頸。
2. 功能
- 表的讀取順序
- 數(shù)據(jù)讀取操作的操作類型
- 哪些索引可以使用
- 哪些索引被實際使用
- 表之間的應(yīng)用
- 每張表有多少行被優(yōu)化器查詢
3. 使用方法
Explain+SQL語句,例如
# 創(chuàng)建唯一索引 CREATE TABLE tab1( id INT(5) NOT NULL, name CHAR(20) NOT NULL, UNIQUE INDEX uniqId(id) ); # 查看索引使用信息 EXPLAIN SELECT * FROM tab1 WHERE id = 1;
4.執(zhí)行計劃包含的信息
id: select查詢的序列號,包含一組數(shù)字,表示查詢中執(zhí)行select子句或操作表的順序
- id相同,執(zhí)行順序由上至下
- id不同,如果是子查詢,id的序號會遞增,id值越大優(yōu)先級越高,越先被執(zhí)行
- id相同不同,同時存在
select_type:查詢的類型,主要是用于區(qū)別普通查詢、聯(lián)合查詢、子查詢等的復(fù)雜查詢
- SIMPLE:簡單的select查詢,查詢中不包含子查詢或者UNION。
- PRIMARY:查詢中包含任何復(fù)雜的子部分,最外層查詢則被標(biāo)記為PRIMARY。
- SUBQUERY:在FROM列表中包含的子查詢被標(biāo)記為DERIVED(衍生),MySQL會遞歸執(zhí)行這些子查詢,把結(jié)果放在臨時表里。
- DERIVED:在FROM列表中包含的子查詢被標(biāo)記為DERIVED(衍生)。MySQL會遞歸執(zhí)行這些子查詢,把結(jié)果放在臨時表里。
- UNION:若第二個SELECT出現(xiàn)在UNION之后,則被標(biāo)記為UNION;若UNION包含在FROM子句的子查詢中,外層SELECT將被標(biāo)記為:DERIVED。
- UNION RESULT:從UNION表中獲取結(jié)果的SELECT。
table:顯示這一行的數(shù)據(jù)是關(guān)于哪些表的。
type:顯示的是訪問類型,是較為重要的一個指標(biāo)
結(jié)果值從最好到最壞依次是:system>const>eq_ref>ref>range>index>All
- system:表只有一行記錄(等于系統(tǒng)表),這是const類型的特例,平時不會出現(xiàn),這個也可以忽略不計。
- const:表示通過索引一次就找到了,const用于比較primary key或則unique索引。因為只匹配一行數(shù)據(jù),所以很快。如將主鍵置于where列表中,MySQL就能將該查詢轉(zhuǎn)換為一個常量。
- eq_ref:唯一性索引掃描,對于每個索引鍵,表中只有一條記錄與之匹配。常見于主鍵或唯一索引掃描。
- ref:非唯一性索引掃描,返回匹配某個單獨值的所有行。本質(zhì)上也是一種索引訪問,它返回所有匹配某個單獨值的行,然而,它可能會找到多個符合條件的行,所以它應(yīng)該屬于查找和掃描的混合體。
- range:只檢索給定范圍的行,使用一個索引來選擇行。key列顯示使用了哪個索引。一般就是在你的where語句中出現(xiàn)了between、<、>、in等的查詢。這種范圍掃描索引掃描比全表掃描要好,因為它只需要開始于索引的某一點,而結(jié)束于另一點,不會掃描全部索引。
- index:Full Index Scan,index與All區(qū)別為index類型只遍歷索引樹。這通常比All快,因為索引文件通常比數(shù)據(jù)文件小。(也就是說雖然all和index都是讀全表,但index是從索引中讀取的,而all是從硬盤中讀的)
- all:Full Table Scan,將遍歷全表以找到匹配的行。
一般來說,得保證查詢至少達(dá)到range級別,最好能達(dá)到ref。
possible_keys:顯示可能應(yīng)用在這張表中的索引,一個或多個。查詢涉及到的字段上若存在索引,則該索引將被列出。但不一定被查詢實際使用。
key:實際使用的索引。如果為NULL,則沒有使用索引。查詢中若使用了覆蓋索引,則該索引僅出現(xiàn)在key列表中,不會出現(xiàn)在possible_keys列表中。(覆蓋索引:查詢的字段與建立的復(fù)合索引的個數(shù)一一吻合)
key_len:表示索引中使用的字節(jié)數(shù),可通過該列計算查詢中使用的索引的長度。在不損失精確性的情況下,長度越短越好。key_len顯示的值為索引字段的最大可能長度,并非實際使用長度,即key_len是根據(jù)表定義計算而得,不是通過表內(nèi)檢索出的。
ref:顯示索引的哪一列被使用了,如果可能的話,是一個常數(shù)。哪些列或常量被用于查找索引列上的值。查詢中與其它表關(guān)聯(lián)的字段,外鍵關(guān)系建立索引。
rows:根據(jù)表統(tǒng)計信息及索引選用情況,大致估算出找到所需的記錄所需要讀取的行數(shù)。
Extra:包含不適合在其他列中顯示但十分重要的額外信息。
- Using filesort:說明mysql會對數(shù)據(jù)使用一個外部的索引排序,而不是按照表內(nèi)的索引順序進(jìn)行讀取。MySQL中無法利用索引完成的排序操作成為“文件排序”。
- Using temporary:使用了臨時表保存中間結(jié)果,MySQL在對查詢結(jié)果排序時使用臨時表。常見于排序order by和分組查詢group by。
- Using index:表示相應(yīng)的select操作中使用了覆蓋索引(Covering Index),避免訪問了表的數(shù)據(jù)行,效率不錯!如果同時出現(xiàn)using where,表明索引被用來執(zhí)行索引鍵值的查找;如果沒有同時出現(xiàn)using where,表明索引用來讀取數(shù)據(jù)而非執(zhí)行查找動作。
- Using where:表明使用了where過濾。
- Using join buffer:使用了連接緩存。
- impossible where:where子句的值總是false,不能用來獲取任何元組。(查詢語句中where的條件不可能被滿足,恒為False)
- select tables optimized away:在沒有GROUPBY子句的情況下,基于索引優(yōu)化MIN/MAX操作或者對于MyISAM存儲引擎優(yōu)化COUNT(*)操作,不必等到執(zhí)行階段再進(jìn)行計算,查詢執(zhí)行計劃生成的階段即完成優(yōu)化。
- distinct:優(yōu)化distinct操作,在找到第一匹配的元組后即停止找相同值的動作。
單表索引優(yōu)化案例分析
#創(chuàng)建表的SQL語句 CREATE TABLE article( id INT UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT, author_id INT(10) UNSIGNED NOT NULL, category_id INT(10) UNSIGNED NOT NULL, views INT(10) UNSIGNED NOT NULL, comments INT(10) UNSIGNED NOT NULL, title VARBINARY(255) NOT NULL, content TEXT NOT NULL ); INSERT INTO article(author_id,category_id,views,comments,title,content) VALUES(1,1,1,1,'1','1'),(2,2,2,2,'2','2'),(3,3,3,3,'3','3');
在沒有創(chuàng)建索引的時候,使用explain查看執(zhí)行計劃
# 查詢category_id=1 且comments>1的情況下,views最多的article_id EXPLAIN SELECT id,author_id FROM article WHERE category_id=1 AND comments>1 ORDER BY views DESC LIMIT 1;
結(jié)論:type是ALL,最壞的情況,extra中出現(xiàn)了using filesort,也是最壞的情況,必須進(jìn)行優(yōu)化
#開始優(yōu)化 #創(chuàng)建索引 #alter table article add index idx_article_ccv(category_id,comments,views); CREATE INDEX idx_article_ccv ON article(category_id,comments,views); #第二次explain EXPLAIN SELECT id,author_id FROM article WHERE category_id=1 AND comments>1 ORDER BY views DESC LIMIT 1;
type變成了range,這是可以忍受的,但是extra里using filesort是無法接受的。
但是已經(jīng)創(chuàng)建了索引,為什么沒有用?因為按照Btree索引的工作原理,先降序category_id,如果遇到相同的category_id,再排序comments,如果遇到相同的comments,再排序views。
當(dāng)comments字段在聯(lián)合索引中處于中間位置時,因comments>1條件是一個范圍值,故MySQL無法利用索引再對后面的views部分進(jìn)行檢索,即range類型查詢字段后面的索引無效。
#刪除第一次創(chuàng)建的索引 DROP INDEX idx_article_ccv ON article; #第2次新建索引 CREATE INDEX idx_article_cv ON article(category_id,views); #第3次explain EXPLAIN SELECT id,author_id FROM article WHERE category_id=1 AND comments>1 ORDER BY views DESC LIMIT 1;
結(jié)論:type變成ref,extra中的using filesort也消失了,結(jié)果非常理想。
索引失效
以具體的案例說明失效的情況,首先先創(chuàng)建員工表和索引:
#創(chuàng)建員工表 CREATE TABLE staffs( id INT PRIMARY KEY AUTO_INCREMENT, NAME VARCHAR(24) NOT NULL DEFAULT "" COMMENT '姓名', age INT NOT NULL DEFAULT 0 COMMENT '年齡', pos VARCHAR(20) NOT NULL DEFAULT "" COMMENT '職位', add_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT'入職時間' ) CHARSET utf8 COMMENT '員工記錄表'; INSERT INTO staffs(NAME,age,pos,add_time) VALUES('z3',22,'manager',NOW()),('july',23,'dev',NOW()),('2000',23,'dev',NOW()); #創(chuàng)建索引 ALTER TABLE staffs ADD INDEX idx_staffs_nameAgePos(NAME,age,pos);
1.聯(lián)合索引(符合索引)不使用第一部分
創(chuàng)建聯(lián)合索引,但是沒有遵循最左前綴法則,則會出現(xiàn)索引失效的情況。
如果索引了多列,要遵守最左前綴法則。
指的是查詢從索引的最左前列開始并且不跳過索引中的列。(帶頭大哥不能死,中間兄弟不能斷哈哈哈)
2.where條件有數(shù)學(xué)運算或函數(shù)
3.mysql在使用不等于(!=或者<>)的時候無法使用索引會導(dǎo)致全表掃描
4. mysql在使用 is null,is not null也無法使用索引
5. like以通配符開頭(‘%abc…’)mysql索引失效會變成全表掃描的操作,當(dāng)%加在右邊時可以使用
6. 字符串不加單引號索引失效
7. where條件使用or
注意:要想使用or,又想讓索引生效,只能將or條件中的每個列都加上索引
總結(jié)
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
MySQL對小數(shù)進(jìn)行四舍五入的操作實現(xiàn)
數(shù)學(xué)函數(shù)是MySQL中常用的一類函數(shù),其主要用于處理數(shù)字,包括整型和浮點數(shù)等等,本文主要介紹了MySQL對小數(shù)進(jìn)行四舍五入的操作實現(xiàn),具有一定的參考價值,感興趣的可以了解一下2023-08-08MySQL ClickHouse常用表引擎超詳細(xì)講解
這篇文章主要介紹了MySQL ClickHouse常用表引擎,ClickHouse表引擎中,CollapsingMergeTree和VersionedCollapsingMergeTree都能通過標(biāo)記位按規(guī)則折疊數(shù)據(jù),從而達(dá)到更新和刪除的效果2022-11-11mysql優(yōu)化之慢查詢分析+explain命令分析+優(yōu)化技巧總結(jié)
這篇文章主要介紹了mysql優(yōu)化之慢查詢分析,explain命令分析,優(yōu)化技巧總結(jié),需要的朋友可以參考下2023-02-02MySQL無法啟動、無法停止解決方法(安全設(shè)置后容易出現(xiàn))
最近在Win2003上的MySQL出現(xiàn)過多次正常運行時無法連接數(shù)據(jù)庫故障,根本原因就是因為安全設(shè)置以后容易出現(xiàn)的問題,其實很簡單的解決2012-03-03