Mysql 如果有多个可选条件怎么加索引_MySQL|mysql-索引
1、索引是什么
1.1索引簡介
索引是表的目錄,是數據庫中專門用于幫助用戶快速查詢數據的一種數據結構。類似于字典中的目錄,查找字典內容時可以根據目錄查找到數據的存放位置,以及快速定位查詢數據。對于索引,會保存在額外的文件中。
1.2主要注意的地方:
(1).索引可以提高查詢速度,會減慢寫入速度,索引的缺點時創建和維護索引需要耗費時間。
(2).索引并不是越多越好,索引固然可以提高相應的select的效率,但同時也降低了insert及update的效率,因為insert或update是有可能會重建索引。
1.3什么樣的字段適合創建索引
(1).表的主鍵、外鍵必須有索引;外鍵是唯一的,而且經常會用來查詢。
(2).經常與其他表進行連接的表,在連接字段上應該建立索引。
(3).數據量超過300的表應該有索引。
(4).重要的SQL或調用頻率高的SQL,比如經常出現在where子句中的字段,order by,group by, distinct的字段都要添加索引。
(5).經常用到排序的列上,因為索引已經排序。
(6).經常用在范圍內搜索的列上創建索引,因為索引已經排序了,其指定的范圍是連續的。
1.4什么場景不適合創建索引
1.對于那些在查詢中很少使用或者參考的列不應該創建索引,這是因為,既然這些列很少使用到,因此有索引或者無索引,并不能提高查詢速度。相反,由于增加了索引,反而降低了系統的維護速度和增大了空間需求。
2.對于那 些只有很少數據值的列也不應該增加索引。因為本來結果集合就是相當于全表查詢了,所以沒有必要。這是因為,由于這些列的取值很少,例如人事表的性別列,在查詢的結果中,結果集的數據行占了表中數據行的很大比 例,即需要在表中搜索的數據行的比例很大。增加索引,并不能明顯加快檢索速度。
3.對于那些定義為text, image和bit數據類型的列不應該增加索引。這是因為,這些列的數據量要么相當大,要么取值很少。
4、當修改性能遠遠大于檢索性能時,不應該創建索引。這是因為,修改性能和檢索性能是互相矛盾的。當增加索引時,會提高檢索性能,但是會降低修改性能。當減少索引時,會提高修改性能,降低檢索性能。因 此,當修改性能遠遠大于檢索性能時,不應該創建索引。
5.不會出現在where條件中的字段不該建立索引。
6.如果列均勻分布在 1 和 100 之間,卻只是查詢中where key_part1 > 1 and key_part1 < 90不應該增加索引
1.5索引使用以及設計規范
1、越小的數據類型通常更好:越小的數據類型通常在磁盤、內存和CPU緩存中都需要更少的空間,處理起來更快。簡單的數據類型更好:整型數據比起字符,處理開銷更小,因為字符串的比較更復雜
2、盡量避免null:應該指定列為not null, 含有空值的列很難進行查詢優化,因為它們使得索引、索引的統計信息以及比較運算更加復雜,也可能導致復合索引無效
3、主鍵選擇策略
每個表必須顯示指定主鍵;
主鍵盡量為一個字段,且為數字類型,避免使用字符串;
主鍵盡量保持增長趨勢,建議使用id的生成器;
4)主鍵盡量杜絕聯合索引
4、每個表的索引個數盡量少于5個,避免創建重復冗余索引;每個組合索引盡量避免超過3個字段,索引不是越多越好,謹慎添加索引,綜合考慮數據分布和數據更新
5、重要的SQL或調用頻率高的SQL
update/select/delete的where條件列字段都要添加索引;
order by , group by, distinct的字段都要添加索引
6、避免出現index merge(單索引or的查詢);合理利用covering index
7、組合索引創建時,把區分度(選擇性)高的字段放在前面;根據SQL的特性,調整組合索引的順序
8、對于varchar字段加索引,建議使用前綴索引,從而減小索引大小
2、索引的創建和刪除
2.1創建數據表時創建索引的基本語法結構:
create table 表名(字段名1 數據類型 [約束條件...]字段名2 數據類型 [約束條件...]...[UNIQUE|FULLTEXT|SPATIAL] INDEX|KEY [索引名] (被用作索引的字段名[(長度)] [ASC|DESC]));#[]中的內容可加可不加,看具體情況; |:表示’或者’ 字段名就是表的列名
2.2直接創建索引的基本語法結構:
create [UNIQUE|FULLTEXT|SPATIAL] INDEX|KEY [索引名] on 表名 (被用作索引的字段名[(長度)] [ASC|DESC]));2.3修改表結構的方式添加索引的基本語法:
alter table 表名 add 索引格式;2.4刪除索引:
drop index 索引名 on 表名;2.5以上出現的索引屬性名的含義:
UNIQUE:(unique),可選參數,表示索引為唯一索引。
FULLTEXT:(fulltext) ,可選參數,表示索引為全文索引。
SPATIAL:(spatial) ,可選參數,表示索引為空間索引。
INDEX | KEY:(index | key), 必選參數,用于指定字段為索引的,用戶在選擇時,只需要二選一即可。
[索引名]:可選參數,其作用是給創建的索引取新名稱。(起到方便使用的目的)
被選定的字段名:必選參數,被用作索引的對應的字段名稱,該字段必須被預先定義。
長度:可選參數,其指索引的長度,必須是字符串類型才可以使用。(比如:電話號碼)
[ASC | DESC]:(asc | desc),可選參數,ASC 表示升序排列,DESC 表示降序排列。
3、索引類型
索引有很多種類型,可以為不同的場景提供更好的性能。在MySQL中,索引是在存儲引擎層而不是服務層。所以,并沒有統一的索引標準:不同的存儲引擎的索引的工作方式并不一樣,也不是所有的存儲引擎都支持所有類型的索引。
3.1普通索引
創建普通索引,不需要添加 [UNIQUE | FULLTEXT | SPATIAL ] 等任何參數進行約束。
- 普通索引 (由關鍵字KEY或INDEX定義的索引) 的唯一任務是加快對數據的訪問速度。
- 只為那些最經常出現在‘查詢條件’(WHERE column = …) 或‘排序條件’(ORDER BYcolumn)中的數據列,來創建索引。
- 只要有可能,就應該選擇一個數據最整齊、最緊湊的數據列(如一個int整數類型的數據列)來創建索引。
建表語句:
create table person(id int(11) not null auto_increment,name varchar(20) default null,primary key (id),key (name) using btree) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;添加索引:
create index name on person(name);3.2唯一索引(主鍵)
創建唯一索引時,使用 UNIQUE 參數對 INDEX | KEY 進行約束。
- 與普通索引類似,不同的就是:索引列的值必須唯一,但允許有空值(注意和主鍵不同)。如果是組合索引,則列值的組合必須唯一,創建方法和普通索引類似。
- 如果能確定某個數據列將只包含彼此各不相同的值,在為這個數據列創建索引的時候就應該用關鍵字UNIQUE把它定義為一個唯一索引。這么做的好處:一是簡化了MySQL對這個索引的管理工作,這個索引也因此而變得更有效率;二是MySQL會在有新記錄插入數據表時,自動檢查新記錄的這個字段的值是否已經在某個記錄的這個字段里出現過了;如果是,MySQL將拒絕插入那條新記錄。也就是說,唯一索引可以保證數據記錄的唯一性。
- 事實上,在許多場合,人們創建唯一索引的目的往往不是為了提高訪問速度,而只是為了避免數據出現重復。
- 主索引:在前面已經反復多次強調過!必須為主鍵字段創建一個索引,這個索引就是所謂的"主索引"。
- 主索引 與 唯一索引的唯一區別是:前者在定義時使用的關鍵字是PRIMARY而不是UNIQUE。
eg:創建的表名為 address 的數據表,并在該表的 id 字段上建立名稱為 address_id 的唯一索引,
建表語句:
create table address(id int(11) auto_increment primary key not null,name varchar(50),address varchar(200),UNIQUE INDEX address_id (id ASC) # id 字段設為唯一索引,并賦予新名字address_id ,且ASC升序排列) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;3.3全文索引
全文索引只能作用在 CHAR、VARCHAR、TEXT、類型的字段上。創建全文索引需要使用 FULLTEXT 參數進行約束。
-
MySQL從3.23.23版開始支持全文索引和全文檢索,fulltext索引僅可用于 MyISAM表;他們可以從CHAR、VARCHAR或TEXT列中作為CREATE TABLE語句的一部分被創建,或是隨后使用ALTER TABLE或CREATE INDEX被添加。
-
對于較大的數據集,將你的資料輸入一個沒有FULLTEXT索引的表中,然后創建索引,其速度比把資料輸入現有FULLTEXT索引的速度更為快。不過切記對于大容量的數據表,生成全文索引是一個非常消耗時間非常消耗硬盤空間的做法。
-
文本字段上的普通索引只能加快對出現在字段內容最前面的字符串(也就是字段內容開頭的字符)進行檢索操作。如果字段里存放的是由幾個、甚至是多個單詞構成的較大段文字,普通索引就沒什么作用了。這種檢索往往以LIKE%word%的形式出現,這對MySQL來說很復雜,如果需要處理的數據量很大,響應時間就會很長。
-
這類場合正是全文索引(full-textindex)可以大顯身手的地方。在生成這種類型的索引時,MySQL將把在文本中出現的所有單詞創建為一份清單,查詢操作將根據這份清單去檢索有關的數據記錄。全文索引即可以隨數據表一同創建,也可以等日后有必要時再使用命令添加。
-
有了全文索引,就可以用SELECT查詢命令去檢索那些包含著一個或多個給定單詞的數據記錄了。下面是這類查詢命令的基本語法: SELECT * FROM table_name
- WHERE MATCH(column1, column2)
- AGAINST(‘word1’, ‘word2’, ‘word3’)
- 上面這條命令將把column1和column2字段里有word1、word2和word3的數據記錄全部查詢出來。
eg:創建的表名為 cards 的數據表,并在該表的 name 字段上建立名稱為 cards_number 的全文索引
建表語句:
create table cards(id int(11) auto_increment primary key not null ,name varchar(20) default null,number bigint(11),info varchar(50),FULLTEXT KEY cards_number (name) # name字段設為全文索引,并賦予新名字cards_number) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;3.4單列索引
創建單列索引,即在數據表的單個字段上創建索引。創建該類型索引不需要引入約束參數,用戶在建立時只需要指定單列字段名,即可創建單列索引。
- 多個單列索引與單個多列索引的查詢效果不同,因為執行查詢時,MySQL只能使用一個索引,會從多個索引中選擇一個限制最為嚴格的索引。
eg:創建的表名為 telephone 的數據表,并在該表的 tel 字段上建立名稱為 tel_num 的單列索引
create table telephone(
id int(11) primary key auto_increment not null,name varchar(10) not null,tel varchar(50) not null,index tel_num (tel(20)) # tel字段設為單列索引,并賦予新名字tel_num,由于tel字段是字符串類型,因此可以設定'索引長度20');3.5多列索引
創建多列索引,即在數據表的多個字段上創建索引。與上述單列索引類似,創建該類型索引不需要引入約束參數。
- 多個單列索引與單個多列索引的查詢效果不同,因為執行查詢時,MySQL只能使用一個索引,會從多個索引中選擇一個限制最為嚴格的索引。
eg:創建的表名為 information 的數據表,并在該表的 name 和 sex 字段上建立名稱為 info 的多列索引
create table information(inf_id int(11) auto_increment primary key not null,name varchar(20) not null,sex varchar(5) not null,birthday varchar(50) not null,index info (name,sex) # name,sex字段設為多列索引,并賦予新名字info);- 注意:在多列索引中,只有查詢條件中使用了這些字段中的第一個字段(即上面示例中的 name 字段),索引才會被使用。觸發多列索引的條件是用戶必須使用索引的第一字段,如果沒有用到第一字段,則索引不起任何作用,用戶想要優化查詢速度,可以應用該類索引形式。
3.6空間索引
創建空間索引,需要添加 SPATIAL 參數進行約束。同樣,必須說明的是,只有 MyISAM 類型的表支持該類型 ‘ 空間索引 ’。而且,索引字段必須有非空約束。
eg:創建的表名為 list 的數據表,并在該表的 goods 字段上建立名稱為 listinfo 的空間索引,這里 goods 字段有非空約束,
create table list(id int(11) primary key auto_increment not null,goods geometry not null,SPATIAL INDEX listinfo (goods) # 這里goods字段有非空約束,符合條件 goods字段設為空間索引,并賦予新名字listinfo)engine=MyISAM;注意: goods 字段上已經建立名稱為 listinfo 的空間索引,其中 goods 字段必須不能為空,且數據類型是 GEOMETRY,該類型是空間數據類型。
空間類型不能用其他類型代替,否則在生成空間素引時會產生錯誤且不能正常創建該類型索引。
外鍵索引:如果為某個外鍵字段定義了一個外鍵約束條件,MySQL就會定義一個內部索引來幫助自己以最有效率的方式去管理和使用外鍵約束條件。
另外:INDEX | KEY:(index | key), 必選參數,用于指定字段為索引的,用戶在選擇時,只需要二選一即可。
區別:
1). key :是數據庫的物理結構,它包含兩層意義:一是約束(偏重于約束和規范數據庫的結構完整性)、二是索引(輔助查詢用的)。包括primary key, unique key, foreign key 等。primary key 有兩個作用,一是約束作用(constraint),用來規范一個存儲主鍵和唯一性,但同時也在此key上建立了一個index;unique key 也有兩個作用,一是約束作用(constraint),規范數據的唯一性,但同時也在這個key上建立了一個index;foreign key也有兩個作用,一是約束作用(constraint),規范數據的引用完整性,但同時也在這個key上建立了一個index;
2). index:是數據庫的物理結構,它包含一層意義:它只是索引(輔助查詢用的),它創建時會在另外的表空間(mysql中的innodb表空間)以一個類似目錄的結構存儲。因此,索引只是索引,它不會去約束索引的字段的行為(那是key要做的事情)。
3.7聚簇索引
1.聚簇索引并不是一種單獨索引,而是一種數據儲存方式。InnoDB 的聚簇索引實際上在同一結構中保存了B-Tree 索引和數據行。
2.當表有聚簇索引時,它的數據行實際上存放在索引的葉子頁中。“聚簇”表示數據行和相鄰的鍵值緊湊的儲存在一起。
3.對應InnoDB 來說如果表沒有定義主鍵,會選擇一個唯一的非空索引代替。如果沒有這樣的索引InnoDB 會隱式定義一個主鍵來作為聚簇索引。InnoDB 只聚集在同一頁面中的記錄。
4.聚簇索引的優勢:
(1)可以把相關數據保存在一起。(2)數據訪問更快。數據和索引保存在同一個 B-Tree 。(3)使用覆蓋索引掃描的查詢可以直接使用頁節點的主鍵值
5.聚簇索引的缺點:
(1)聚簇索引最大的提高了I/O密集型應用的性能,但如果數據全部都放到內存中,則數據的順序就沒有那么重要了,聚簇索引也就沒什么優勢了。(2)插入速度嚴重依賴插入順序。按照主鍵插入的方式是InnoDB 速度最快的方式,但如果不是按照主鍵順序加載數據,那么在加載后最好使用OPTIMIZE TABLE 命令重新組織一2下表(3)更新聚簇索引列的代價很高。因為會強制InnoDB 將每個被更新的行移動到新的位置
6.二級索引
主鍵索引的葉子節點存的是整行數據,在InnoDB 里,主鍵索引也被稱為聚簇索引非主鍵索引的葉子節點內容是主鍵的值。在InnoDB 里。非主鍵索引也被稱為二級索引。如:select* from order where user_id=3; user_id是普通索引。則會先搜索user_id 的索引樹,得到id=5,再到id 索引樹搜索一次,這個過程就是 “回表”。也就是說非主鍵索引需要查詢2次
3.8覆蓋索引
1.mysql 可以使用索引直接來獲取列的數據,這樣就可以不再需要讀取數據行。如果索引的葉子節點中已經包含要查詢的數據,那么還有什么必要再回表查詢呢?如果一個索引包含(覆蓋)所有要查詢的字段的值,那么就稱為“覆蓋索引”
2.覆蓋索引可以提高查詢的性能,不需要回表,好處是:
(1)索引條目通常小于數據行,如果只需讀取索引,那么mysql 就會減少訪問量(2)索引是按照列值順序存儲的,索引I/O 密集型的范圍查詢會比隨機從磁盤讀取每一行數據的I/O 要少得多(3)一些存儲引擎如MyISAM 在內存只緩存索引,數據則依賴操作系統來緩存,因此要訪問數據需要一次系統調用,這可能導致嚴重的性能問題,尤其是那些系統調用占了數據訪問中最大開銷的場景(4)InnoDB 的聚簇索引,覆蓋索引對InnoDB 表的特別有用。InnoDB 的二級索引在葉子節點保存了行的主鍵值,所以如果二級主鍵能夠覆蓋查詢,則可以避免對主鍵索引的二次查詢。
select * from order where user_id between 1 and 3一旦用了select *,就會有其他列需要讀取,這時在讀完index以后還需要去讀data才會返回結果。
這兩種處理方式性能差異非常大,特別是返回行數比較多,并且讀數據需要 I/O 的時候,可能會有幾十上百倍的差異。因此建議根據需要用select *
4、索引原理
4.1索引實現的數據結構
Mysql對于不同的存儲引擎,索引的實現實現方式是不同的。主流的存儲引擎:MyISAM和InnoDB,兩種存儲引擎都使用B+Tree(B-Tree的變種)作為索引結構,但是在實現方式上,卻有很大的不同。下面是兩種BTree數據結構:
B-tree結構:
B-Tree無論是葉子結點還是非葉子結點,都含有key和一個指向數據的指針,只要找到某個節點后,就可以根據指針找到磁盤地址從而找到數據。
B+tree結構:
B+Tree所有葉子結點才有指向數據的指針。非葉子結點就是純索引數據和主鍵。每個葉子結點都有指向下一個葉子結點的鏈接。
小結:非葉子結點存放在內存中,也叫內結點,因此,在有限的內存中, B-Tree中每個數據的指針會帶來額外的內存占用,減少了放入內存的非葉子結點數;B+Tree則盡可能多地將非葉子結點放入內存中
4.2MySQL中索引實現
由于B+Tree數據結構的優勢,目前mysql基本都采用B+Tree方式實現索引,下面列出了兩個最常用的存儲引擎的索引實現:
1、MyISAM:如下圖,葉子結點的data域存放的是數據的地址:
上圖表中共三列數據,col1為主鍵,表示MyISAM表的主索引示意圖,在MyISAM中,主索引和輔助索引(除主鍵以外的其它索引)在結構上沒有任何區別,只是主索引的key是唯一的,輔助索引的key可以重復。
2、InnoDB:對比MyISAM,InnoDB的主鍵索引與輔助索引存儲方式是不同的:
主鍵索引:主鍵索引的葉子結點存放的是key值和數據,葉子結點載入內存時,數據一起載入,找到葉子結點的key,就找到了數據。
輔助索引:輔助索引的葉子結點存放的是key值和對應的記錄的主鍵值,使用輔助索引查詢,首先檢索輔助索引獲取主鍵,然后用主鍵在主索引中檢索獲取記錄。
小結:MyISAM索引葉子節點存放的是數據的地址,主鍵索引與輔助索引除了值得唯一性在結構上完全一樣。InnoDB索引葉子節點存放的內容因索引類型不同而不同,主鍵索引葉子節點存放的是數據本身,輔助索引葉子節點上存放的是主鍵值。
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的Mysql 如果有多个可选条件怎么加索引_MySQL|mysql-索引的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 第四范式@2020 WAIC世界人工智能
- 下一篇: 第四范式与赛诺贝斯达成战略合作,开启Ma