首先來看看表是否有索引的命令
創(chuàng)新互聯(lián)公司自2013年起,是專業(yè)互聯(lián)網(wǎng)技術(shù)服務(wù)公司,擁有項目成都網(wǎng)站設(shè)計、做網(wǎng)站網(wǎng)站策劃,項目實施與項目整合能力。我們以讓每一個夢想脫穎而出為使命,1280元方城做網(wǎng)站,已為上家服務(wù),為方城各地企業(yè)和個人服務(wù),聯(lián)系電話:18980820575
show index from 表名;
看到主鍵索引,索引類型是BTREE(二叉樹)
正是因為這個二叉樹算法,讓查詢速度快很多,二叉樹的原理,就是取最中間的一個數(shù),然后把大于這個數(shù)的往右邊排,小于這個數(shù)的就向左排,每次減半,然后依次類推,每次減半,形成一個樹狀結(jié)構(gòu)圖
例如上面的例子,我們不使用索引的話,需要查詢11次才把編號為4的數(shù)據(jù)取出,如果加上索引,我們只需要4次就可以取出。
如大家所知道的,MySQL目前主要有以下幾種索引類型:FULLTEXT,HASH,BTREE,RTREE。
那么,這幾種索引有什么功能和性能上的不同呢?
FULLTEXT
即為全文索引,目前只有MyISAM引擎支持。其可以在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ù)寫入的速度快很多。
全文索引并不是和MyISAM一起誕生的,它的出現(xiàn)是為了解決WHERE name LIKE “%word%"這類針對文本的模糊查詢效率較低的問題。在沒有全文索引之前,這樣一個查詢語句是要進行遍歷數(shù)據(jù)表操作的,可見,在數(shù)據(jù)量較大時是極其的耗時的,如果沒有異步IO處理,進程將被挾持,很浪費時間,當然這里不對異步IO作進一步講解,想了解的童鞋,自行谷哥。
全文索引的使用方法并不復(fù)雜:
創(chuàng)建ALTER TABLE table ADD INDEX `FULLINDEX` USING FULLTEXT(`cname1`[,cname2…]);
使用SELECT * FROM table WHERE MATCH(cname1[,cname2…]) AGAINST ('word' MODE );
其中, MODE為搜尋方式(IN BOOLEAN MODE ,IN NATURAL LANGUAGE MODE ,IN NATURAL LANGUAGE MODE WITH QUERY EXPANSION / WITH QUERY EXPANSION)。
關(guān)于這三種搜尋方式,愚安在這里也不多做交代,簡單地說,就是,布爾模式,允許word里含一些特殊字符用于標記一些具體的要求,如+表示一定要有,-表示一定沒有,*表示通用匹配符,是不是想起了正則,類似吧;自然語言模式,就是簡單的單詞匹配;含表達式的自然語言模式,就是先用自然語言模式處理,對返回的結(jié)果,再進行表達式匹配。
對搜索引擎稍微有點了解的同學,肯定知道分詞這個概念,F(xiàn)ULLTEXT索引也是按照分詞原理建立索引的。西文中,大部分為字母文字,分詞可以很方便的按照空格進行分割。但很明顯,中文不能按照這種方式進行分詞。那又怎么辦呢?這個向大家介紹一個Mysql的中文分詞插件Mysqlcft,有了它,就可以對中文進行分詞,想了解的同學請移步Mysqlcft,當然還有其他的分詞插件可以使用。
HASH
Hash這個詞,可以說,自打我們開始碼的那一天起,就開始不停地見到和使用到了。其實,hash就是一種(key=value)形式的鍵值對,如數(shù)學中的函數(shù)映射,允許多個key對應(yīng)相同的value,但不允許一個key對應(yīng)多個value。正是由于這個特性,hash很適合做索引,為某一列或幾列建立hash索引,就會利用這一列或幾列的值通過一定的算法計算出一個hash值,對應(yīng)一行或幾行數(shù)據(jù)(這里在概念上和函數(shù)映射有區(qū)別,不要混淆)。在Java語言中,每個類都有自己的hashcode()方法,沒有顯示定義的都繼承自object類,該方法使得每一個對象都是唯一的,在進行對象間equal比較,和序列化傳輸中起到了很重要的作用。hash的生成方法有很多種,足可以保證hash碼的唯一性,例如在MongoDB中,每一個document都有系統(tǒng)為其生成的唯一的objectID(包含時間戳,主機散列值,進程PID,和自增ID)也是一種hash的表現(xiàn)。額,我好像扯遠了-_-!
由于hash索引可以一次定位,不需要像樹形索引那樣逐層查找,因此具有極高的效率。那為什么還需要其他的樹形索引呢?
在這里愚安就不自己總結(jié)了。引用下園子里其他大神的文章:來自 14的路 的MySQL的btree索引和hash索引的區(qū)別
(1)Hash 索引僅僅能滿足"=","IN"和"="查詢,不能使用范圍查詢。
由于 Hash 索引比較的是進行 Hash 運算之后的 Hash 值,所以它只能用于等值的過濾,不能用于基于范圍的過濾,因為經(jīng)過相應(yīng)的 Hash 算法處理之后的 Hash 值的大小關(guān)系,并不能保證和Hash運算前完全一樣。
(2)Hash 索引無法被用來避免數(shù)據(jù)的排序操作。
由于 Hash 索引中存放的是經(jīng)過 Hash 計算之后的 Hash 值,而且Hash值的大小關(guān)系并不一定和 Hash 運算前的鍵值完全一樣,所以數(shù)據(jù)庫無法利用索引的數(shù)據(jù)來避免任何排序運算;
(3)Hash 索引不能利用部分索引鍵查詢。
對于組合索引,Hash 索引在計算 Hash 值的時候是組合索引鍵合并后再一起計算 Hash 值,而不是單獨計算 Hash 值,所以通過組合索引的前面一個或幾個索引鍵進行查詢的時候,Hash 索引也無法被利用。
(4)Hash 索引在任何時候都不能避免表掃描。
前面已經(jīng)知道,Hash 索引是將索引鍵通過 Hash 運算之后,將 Hash運算結(jié)果的 Hash 值和所對應(yīng)的行指針信息存放于一個 Hash 表中,由于不同索引鍵存在相同 Hash 值,所以即使取滿足某個 Hash 鍵值的數(shù)據(jù)的記錄條數(shù),也無法從 Hash 索引中直接完成查詢,還是要通過訪問表中的實際數(shù)據(jù)進行相應(yīng)的比較,并得到相應(yīng)的結(jié)果。
(5)Hash 索引遇到大量Hash值相等的情況后性能并不一定就會比B-Tree索引高。
對于選擇性比較低的索引鍵,如果創(chuàng)建 Hash 索引,那么將會存在大量記錄指針信息存于同一個 Hash 值相關(guān)聯(lián)。這樣要定位某一條記錄時就會非常麻煩,會浪費多次表數(shù)據(jù)的訪問,而造成整體性能低下。
愚安我稍作補充,講一下HASH索引的過程,順便解釋下上面的第4,5條:
當我們?yōu)槟骋涣谢蚰硯琢薪ash索引時(目前就只有MEMORY引擎顯式地支持這種索引),會在硬盤上生成類似如下的文件:
hash值 存儲地址
1db54bc745a1 77#45b5
4bca452157d4 76#4556,77#45cc…
…
hash值即為通過特定算法由指定列數(shù)據(jù)計算出來,磁盤地址即為所在數(shù)據(jù)行存儲在硬盤上的地址(也有可能是其他存儲地址,其實MEMORY會將hash表導(dǎo)入內(nèi)存)。
這樣,當我們進行WHERE age = 18 時,會將18通過相同的算法計算出一個hash值==在hash表中找到對應(yīng)的儲存地址==根據(jù)存儲地址取得數(shù)據(jù)。
所以,每次查詢時都要遍歷hash表,直到找到對應(yīng)的hash值,如(4),數(shù)據(jù)量大了之后,hash表也會變得龐大起來,性能下降,遍歷耗時增加,如(5)。
BTREE
BTREE索引就是一種將索引值按一定的算法,存入一個樹形的數(shù)據(jù)結(jié)構(gòu)中,相信學過數(shù)據(jù)結(jié)構(gòu)的童鞋都對當初學習二叉樹這種數(shù)據(jù)結(jié)構(gòu)的經(jīng)歷記憶猶新,反正愚安我當時為了軟考可是被這玩意兒好好地折騰了一番,不過那次考試好像沒怎么考這個。如二叉樹一樣,每次查詢都是從樹的入口root開始,依次遍歷node,獲取leaf。
BTREE在MyISAM里的形式和Innodb稍有不同
在 Innodb里,有兩種形態(tài):一是primary key形態(tài),其leaf node里存放的是數(shù)據(jù),而且不僅存放了索引鍵的數(shù)據(jù),還存放了其他字段的數(shù)據(jù)。二是secondary index,其leaf node和普通的BTREE差不多,只是還存放了指向主鍵的信息.
而在MyISAM里,主鍵和其他的并沒有太大區(qū)別。不過和Innodb不太一樣的地方是在MyISAM里,leaf node里存放的不是主鍵的信息,而是指向數(shù)據(jù)文件里的對應(yīng)數(shù)據(jù)行的信息.
RTREE
RTREE在mysql很少使用,僅支持geometry數(shù)據(jù)類型,支持該類型的存儲引擎只有MyISAM、BDb、InnoDb、NDb、Archive幾種。
相對于BTREE,RTREE的優(yōu)勢在于范圍查找.
各種索引的使用情況
(1)對于BTREE這種Mysql默認的索引類型,具有普遍的適用性
(2)由于FULLTEXT對中文支持不是很好,在沒有插件的情況下,最好不要使用。其實,一些小的博客應(yīng)用,只需要在數(shù)據(jù)采集時,為其建立關(guān)鍵字列表,通過關(guān)鍵字索引,也是一個不錯的方法,至少愚安我是經(jīng)常這么做的。
(3)對于一些搜索引擎級別的應(yīng)用來說,F(xiàn)ULLTEXT同樣不是一個好的處理方法,Mysql的全文索引建立的文件還是比較大的,而且效率不是很高,即便是使用了中文分詞插件,對中文分詞支持也只是一般。真要碰到這種問題,Apache的Lucene或許是你的選擇。
(4)正是因為hash表在處理較小數(shù)據(jù)量時具有無可比擬的素的優(yōu)勢,所以hash索引很適合做緩存(內(nèi)存數(shù)據(jù)庫)。如mysql數(shù)據(jù)庫的內(nèi)存版本Memsql,使用量很廣泛的緩存工具Mencached,NoSql數(shù)據(jù)庫redis等,都使用了hash索引這種形式。當然,不想學習這些東西的話Mysql的MEMORY引擎也是可以滿足這種需求的。
因為索引多。同一條個數(shù)據(jù),NOSQL占用空間是一般SQL數(shù)據(jù)庫的3-5倍。
你可以理解成NOSQL默認開啟全字段索引和全文索引什么的。
其實在十萬級以下的數(shù)據(jù),只要SQL建好索引的情況并不比NOSQL慢。NOSQL主要是用于千萬上億級的時候。
你有沒有想過如何使用搜索功能在所有整站中實現(xiàn)!互聯(lián)網(wǎng)博客和網(wǎng)站,大多數(shù)都采用MySQL數(shù)據(jù)庫。MySQL提供了一個美妙的方式實施一個小的搜索引擎,在您的網(wǎng)站(全文檢索)。所有您需要做的是擁有的MySQL 4.x及以上。MySQL提供全文檢索功能,我們可以用它來 ??實現(xiàn)搜索功能。
首先,讓我們?yōu)槲覀兊睦又性O(shè)置一個示例表。我們將創(chuàng)建一個名為第一個表。
CREATE TABLE articles (
id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,
title VARCHAR(200),
body TEXT,
FULLTEXT (title,body)
);
在此表中還可以添加一些示例數(shù)據(jù)。執(zhí)行后,插入查詢。
INSERT INTO articles (title,body) VALUES
('MySQL Tutorial','DBMS stands for DataBase ...'),
('How To Use MySQL Well','After you went through a ...'),
('Optimizing MySQL','In this tutorial we will show ...'),
('1001 MySQL Tricks','1. Never run mysqld as root. 2. ...'),
('MySQL vs. YourSQL','In the following database comparison ...'),
('MySQL Security','When configured properly, MySQL ...');
一旦樣本數(shù)據(jù)是準備好,我們可以開始我們的全文檢索功能。
自然語言全文搜索
嘗試我們的示例表上執(zhí)行下面的SELECT查詢。
SELECT * FROM articles
WHERE MATCH (title,body) AGAINST ('database');
你就能看到結(jié)果如下:
在下面的數(shù)據(jù)庫比較5 MySQL與YourSQL的...
MySQL教程DBMS 1代表數(shù)據(jù)庫...
我們在上面的SQL查詢(標題,正文)反對(“數(shù)據(jù)庫”)的比賽,選擇所有的記錄,列標題和正文進行全文搜索。
您可以修改該查詢,并創(chuàng)建您自己的版本,以自己的數(shù)據(jù)庫中執(zhí)行全文搜索。
布爾全文搜索
它可能發(fā)生,你要指定某些關(guān)鍵字在您的搜索條件。此外,您可能要忽略某些關(guān)鍵字。布爾全文搜索可以用來執(zhí)行這些要求的全文檢索。
檢查下面的SELECT查詢。
SELECT * FROM articles WHERE MATCH (title,body)
AGAINST ('+MySQL -YourSQL' IN BOOLEAN MODE);
如果您發(fā)現(xiàn)上述選擇查詢,我們增加了布爾MODE反對()。這個查詢將獲取MySQL的關(guān)鍵字,但不YourSQL關(guān)鍵字的所有記錄。請注意+和-我們以前指定的關(guān)鍵字!
在執(zhí)行此功能,MySQL使用什么有時也被稱為布爾邏輯作為暗示,其中:+代表與-代表不是[無操作員]暗示或
以下是幾個例子布爾搜索條件。
“蘋果香蕉
查找行至少包含兩個詞之一。
“+蘋果+果汁”
尋找包含兩個單詞的行。
“+蘋果Macintosh
查找行包含“蘋果”,但排名的行,如果它們也包含“麥金塔”。
“+蘋果Macintosh的”
查找行包含“蘋果”這個詞,而不是“麥金塔”。
'+蘋果Macintosh的“
查找包含單詞“蘋果”的行,但如果該行也包含單詞“麥金塔”,速度比如果行不低。這是“軟”比“+蘋果Macintosh電腦”,為“麥金塔”的存在,導(dǎo)致該行不能在所有返回的搜索。
'+蘋果+(營業(yè)額餡餅)“
行包含“蘋果”和“營業(yè)額”,或“蘋果”和“餡餅”(任何順序)的話,但排名“蘋果的營業(yè)額”比“蘋果餡餅“。
限制
支持全文檢索的MyISAM表只。MySQL 4.1中,使用多個字符設(shè)置一個單一的表內(nèi)的支持。然而,在一個FULLTEXT索引的所有列,必須使用相同的字符集和校對規(guī)則。MATCH()列列表必須匹配完全在一些列清單表的FULLTEXT索引定義,除非這場比賽()是在布爾模式。布爾模式搜索,可以做非索引列,雖然他們很可能是緩慢的。
使用索引是數(shù)據(jù)庫性能優(yōu)化的必備技能之一。在MySQL數(shù)據(jù)庫中,有四種索引:聚集索引(主鍵索引)、普通索引、唯一索引以及我們這里將要介紹的全文索引(FULLTEXT INDEX)。
全文索引(也稱全文檢索)是目前搜索引擎使用的一種關(guān)鍵技術(shù)。它能夠利用「分詞技術(shù)「等多種算法智能分析出文本文字中關(guān)鍵字詞的頻率及重要性,然后按照一定的算法規(guī)則智能地篩選出我們想要的搜索結(jié)果。在這里,我們就不追根究底其底層實現(xiàn)原理了,現(xiàn)在我們來看看在MySQL中如何創(chuàng)建并使用全文索引。
在MySQL中,創(chuàng)建全文索引相對比較簡單。例如,我們有一個文章表(article),其中有主鍵ID(id)、文章標題(title)、文章內(nèi)容(content)三個字段?,F(xiàn)在我們希望能夠在title和content兩個列上創(chuàng)建全文索引,article表及全文索引的創(chuàng)建SQL語句如下:
--創(chuàng)建article表
CREATE TABLE article (
id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,
title VARCHAR(200),
content TEXT,
FULLTEXT (title, content) --在title和content列上創(chuàng)建全文索引
);
上面就是在創(chuàng)建表的同時建立全文索引的SQL示例。此外,如果我們想要給已經(jīng)存在的表的指定字段創(chuàng)建全文索引,同樣以article表為例,我們可以使用如下SQL語句進行創(chuàng)建:
--給現(xiàn)有的article表的title和content字段創(chuàng)建全文索引
--索引名稱為fulltext_article
ALTER TABLE article
ADD FULLTEXT INDEX fulltext_article (title, content)
在MySQL中創(chuàng)建全文索引之后,現(xiàn)在就該了解如何使用了。眾所周知,在數(shù)據(jù)庫中進行模糊查詢是使用LIKE關(guān)鍵字進行查詢,例如:
SELECT * FROM article WHERE content LIKE '%查詢字符串%'
那么,我們使用全文索引也是這樣用的嗎?當然不是,我們必須使用特有的語法才能使用全文索引進行查詢。例如,我們想要在article表的title和content列中全文檢索指定的查詢字符串,可以如下編寫SQL語句:
SELECT * FROM article WHERE MATCH(title, content) AGAINST('查詢字符串')
強烈注意:MySQL自帶的全文索引只能用于數(shù)據(jù)庫引擎為MyISAM的數(shù)據(jù)表,如果是其他數(shù)據(jù)引擎,則全文索引不會生效。此外,MySQL自帶的全文索引只能對英文進行全文檢索,目前無法對中文進行全文檢索。如果需要對包含中文在內(nèi)的文本數(shù)據(jù)進行全文檢索,我們需要采用Sphinx(斯芬克斯)/Coreseek技術(shù)來處理中文。本站將會在后續(xù)文章中對Sphinx以及Coreseek進行介紹。
備注1:目前,使用MySQL自帶的全文索引時,如果查詢字符串的長度過短將無法得到期望的搜索結(jié)果。MySQL全文索引所能找到的詞的默認最小長度為4個字符。另外,如果查詢的字符串包含停止詞,那么該停止詞將會被忽略。
備注2:如果可能,請盡量先創(chuàng)建表并插入所有數(shù)據(jù)后再創(chuàng)建全文索引,而不要在創(chuàng)建表時就直接創(chuàng)建全文索引,因為前者比后者的全文索引效率要高。