1.對(duì)查詢進(jìn)行優(yōu)化,應(yīng)盡量避免全表掃描,首先應(yīng)考慮在 where 及 order by 涉及的列上建立索引。
2.應(yīng)盡量避免在 where 子句中使用!=或操作符,否則將引擎放棄使用索引而進(jìn)行全表掃描。
3.應(yīng)盡量避免在 where 子句中對(duì)字段進(jìn)行 null 值判斷,否則將導(dǎo)致引擎放棄使用索引而進(jìn)行全表掃描,如:
select id from t where num is null
可以在num上設(shè)置默認(rèn)值0,確保表中num列沒(méi)有null值,然后這樣查詢:
select id from t where num=0
4.應(yīng)盡量避免在 where 子句中使用 or 來(lái)連接條件,否則將導(dǎo)致引擎放棄使用索引而進(jìn)行全表掃描,如:
select id from t where num=10 or num=20
可以這樣查詢:
select id from t where num=10
union all
select id from t where num=20
5.下面的查詢也將導(dǎo)致全表掃描:
select id from t where name like '%abc%'
若要提高效率,可以考慮全文檢索。
6.in 和 not in 也要慎用,否則會(huì)導(dǎo)致全表掃描,如:
select id from t where num in(1,2,3)
對(duì)于連續(xù)的數(shù)值,能用 between 就不要用 in 了:
select id from t where num between 1 and 3
7.如果在 where 子句中使用參數(shù),也會(huì)導(dǎo)致全表掃描。因?yàn)镾QL只有在運(yùn)行時(shí)才會(huì)解析局部變量,但優(yōu)化程序不能將訪問(wèn)計(jì)劃的選擇推遲到運(yùn)行時(shí);它必須在編譯時(shí)進(jìn)行選擇。然而,如果在編譯時(shí)建立訪問(wèn)計(jì)劃,變量的值還是未知的,因而無(wú)法作為索引選擇的輸入項(xiàng)。如下面語(yǔ)句將進(jìn)行全表掃描:
select id from t where num=@num
可以改為強(qiáng)制查詢使用索引:
select id from t with(index(索引名)) where num=@num
8.應(yīng)盡量避免在 where 子句中對(duì)字段進(jìn)行表達(dá)式操作,這將導(dǎo)致引擎放棄使用索引而進(jìn)行全表掃描。如:
select id from t where num/2=100
應(yīng)改為:
select id from t where num=100*2
9.應(yīng)盡量避免在where子句中對(duì)字段進(jìn)行函數(shù)操作,這將導(dǎo)致引擎放棄使用索引而進(jìn)行全表掃描。如:
select id from t where substring(name,1,3)='abc'--name以abc開頭的id
select id from t where datediff(day,createdate,'2005-11-30')=0--'2005-11-30'生成的id
應(yīng)改為:
select id from t where name like 'abc%'
select id from t where createdate>='2005-11-30' and createdate
MySQL可以很好的支持大數(shù)據(jù)量的存取,但是一般說(shuō)來(lái),數(shù)據(jù)庫(kù)中的表越小,在它上面執(zhí)行的查詢也就會(huì)越快。因此,在創(chuàng)建表的時(shí)候,為了獲得更好的性能,我們可以將表中字段的寬度設(shè)得盡可能小。例如,在定義郵政編碼這個(gè)字段時(shí),如果將其設(shè)置為CHAR(255),顯然給數(shù)據(jù)庫(kù)增加了不必要的空間,甚至使用VARCHAR這種類型也是多余的,因?yàn)镃HAR(6)就可以很好的完成任務(wù)了。同樣的,如果可以的話,我們應(yīng)該使用MEDIUMINT而不是 BIGIN來(lái)定義整型字段。
另外一個(gè)提高效率的方法是在可能的情況下,應(yīng)該盡量把字段設(shè)置為NOT NULL,這樣在將來(lái)執(zhí)行查詢的時(shí)候,數(shù)據(jù)庫(kù)不用去比較NULL值。
對(duì)于某些文本字段,例如“省份”或者“性別”,我們可以將它們定義為ENUM類型。因?yàn)樵贛ySQL中,ENUM類型被當(dāng)作數(shù)值型數(shù)據(jù)來(lái)處理,而數(shù)值型數(shù)據(jù)被處理起來(lái)的速度要比文本類型快得多。這樣,我們又可以提高數(shù)據(jù)庫(kù)的性能。
1.存儲(chǔ)引擎的選擇如果數(shù)據(jù)表需要事務(wù)處理,應(yīng)該考慮使用InnoDB,因?yàn)樗耆螦CID特性。如果不需要事務(wù)處理,使用默認(rèn)存儲(chǔ)引擎MyISAM是比較明智的。并且不要嘗試同時(shí)使用這兩個(gè)存儲(chǔ)引擎。思考一下:在一個(gè)事務(wù)處理中,一些數(shù)據(jù)表使用InnoDB,而其余的使用MyISAM.結(jié)果呢?整個(gè)subject將被取消,只有那些在事務(wù)處理中的被帶回到原始狀態(tài),其余的被提交的數(shù)據(jù)轉(zhuǎn)存,這將導(dǎo)致整個(gè)數(shù)據(jù)庫(kù)的沖突。然而存在一個(gè)簡(jiǎn)單的方法可以同時(shí)利用兩個(gè)存儲(chǔ)引擎的優(yōu)勢(shì)。目前大多數(shù)MySQL套件中包括InnoDB、編譯器和鏈表,但如果你選擇MyISAM,你仍然可以單獨(dú)下載InnoDB,并把它作為一個(gè)插件。很簡(jiǎn)單的方法,不是嗎?
2.計(jì)數(shù)問(wèn)題如果數(shù)據(jù)表采用的存儲(chǔ)引擎支持事務(wù)處理(如InnoDB),你就不應(yīng)使用COUNT(*)計(jì)算數(shù)據(jù)表中的行數(shù)。這是因?yàn)樵诋a(chǎn)品類數(shù)據(jù)庫(kù)使用COUNT(*),最多返回一個(gè)近似值,因?yàn)樵谀硞€(gè)特定時(shí)間,總有一些事務(wù)處理正在運(yùn)行。如果使用COUNT(*)顯然會(huì)產(chǎn)生bug,出現(xiàn)這種錯(cuò)誤結(jié)果。
3.反復(fù)測(cè)試查詢查詢最棘手的問(wèn)題并不是無(wú)論怎樣小心總會(huì)出現(xiàn)錯(cuò)誤,并導(dǎo)致bug出現(xiàn)。恰恰相反,問(wèn)題是在大多數(shù)情況下bug出現(xiàn)時(shí),應(yīng)用程序或數(shù)據(jù)庫(kù)已經(jīng)上線。的確不存在針對(duì)該問(wèn)題切實(shí)可行的解決方法,除非將測(cè)試樣本在應(yīng)用程序或數(shù)據(jù)庫(kù)上運(yùn)行。任何數(shù)據(jù)庫(kù)查詢只有經(jīng)過(guò)上千個(gè)記錄的大量樣本測(cè)試,才能被認(rèn)可。
4.避免全表掃描通常情況下,如果MySQL(或者其他關(guān)系數(shù)據(jù)庫(kù)模型)需要在數(shù)據(jù)表中搜索或掃描任意特定記錄時(shí),就會(huì)用到全表掃描。此外,通常最簡(jiǎn)單的方法是使用索引表,以解決全表掃描引起的低效能問(wèn)題。然而,正如我們?cè)陔S后的問(wèn)題中看到的,這存在錯(cuò)誤部分。
5.使用“EXPLAIN”進(jìn)行查詢當(dāng)需要調(diào)試時(shí),EXPLAIN是一個(gè)很好的命令,下面將對(duì)EXPLAIN進(jìn)行深入探討。
mysql的優(yōu)化大的有兩方面:1、配置優(yōu)化 配置的優(yōu)化其實(shí)包含兩個(gè)方面的:操作系統(tǒng)內(nèi)核的優(yōu)化和mysql配置文件的優(yōu)化 1)系統(tǒng)內(nèi)核的優(yōu)化對(duì)專用的mysql服務(wù)器來(lái)說(shuō),無(wú)非是內(nèi)存實(shí)用、連接數(shù)、超時(shí)處理、TCP處理等方面的優(yōu)化,根據(jù)自己的硬件配置來(lái)進(jìn)行優(yōu)化,這里不多講; 2)mysql配置的優(yōu)化,一般來(lái)說(shuō)包含:IO處理的常用參數(shù)、最大連接數(shù)設(shè)置、緩存使用參數(shù)的設(shè)置、慢日志的參數(shù)的設(shè)置、innodb相關(guān)參數(shù)的設(shè)置等,如果有主從關(guān)系在設(shè)置主從同步的相關(guān)參數(shù)即可,網(wǎng)上的相關(guān)配置文件很多,大同小異,常用的設(shè)置大多修改這些差不多就夠用了。
2、sql語(yǔ)句的優(yōu)化1、盡量稍作計(jì)算 Mysql的作用是用來(lái)存取數(shù)據(jù)的,不是做計(jì)算的,做計(jì)算的話可以用其他方法去實(shí)現(xiàn),mysql做計(jì)算是很耗資源的。2.盡量少 join MySQL 的優(yōu)勢(shì)在于簡(jiǎn)單,但這在某些方面其實(shí)也是其劣勢(shì)。
MySQL 優(yōu)化器效率高,但是由于其統(tǒng)計(jì)信息的量有限,優(yōu)化器工作過(guò)程出現(xiàn)偏差的可能性也就更多。對(duì)于復(fù)雜的多表 Join,一方面由于其優(yōu)化器受限,再者在 Join 這方面所下的功夫還不夠,所以性能表現(xiàn)離 Oracle 等關(guān)系型數(shù)據(jù)庫(kù)前輩還是有一定距離。
但如果是簡(jiǎn)單的單表查詢,這一差距就會(huì)極小甚至在有些場(chǎng)景下要優(yōu)于這些數(shù)據(jù)庫(kù)前輩。3.盡量少排序 排序操作會(huì)消耗較多的 CPU 資源,所以減少排序可以在緩存命中率高等 IO 能力足夠的場(chǎng)景下會(huì)較大影響 SQL的響應(yīng)時(shí)間。
對(duì)于MySQL來(lái)說(shuō),減少排序有多種辦法,比如: 通過(guò)利用索引來(lái)排序的方式進(jìn)行優(yōu)化 減少參與排序的記錄條數(shù) 非必要不對(duì)數(shù)據(jù)進(jìn)行排序4.盡量避免 select * 在數(shù)據(jù)量少并且訪問(wèn)量不大的情況下,select * 沒(méi)有什么影響,但是量級(jí)達(dá)到一定級(jí)別的時(shí)候,在執(zhí)行效率和IO資源的使用上,還是有很大關(guān)系的,用什么字段取什么字段,減少不必要的資源浪費(fèi)。 之前遇到過(guò)因?yàn)橐粋€(gè)字段存儲(chǔ)的數(shù)據(jù)比較大,并發(fā)高的情況下把網(wǎng)絡(luò)帶寬跑滿的情況,造成網(wǎng)站打不開或是打開速度極慢的情況。
5.盡量用 join 代替子查詢 雖然 Join 性能并不佳,但是和 MySQL 的子查詢比起來(lái)還是有非常大的性能優(yōu)勢(shì)。MySQL 的子查詢執(zhí)行計(jì)劃一直存在較大的問(wèn)題,雖然這個(gè)問(wèn)題已經(jīng)存在多年,但是到目前已經(jīng)發(fā)布的所有穩(wěn)定版本中都普遍存在,一直沒(méi)有太大改善。
雖然官方也在很早就承認(rèn)這一問(wèn)題,并且承諾盡快解決,但是至少到目前為止我們還沒(méi)有看到哪一個(gè)版本較好的解決了這一問(wèn)題。6.盡量少 or 當(dāng) where 子句中存在多個(gè)條件以“或”并存的時(shí)候,MySQL 的優(yōu)化器并沒(méi)有很好的解決其執(zhí)行計(jì)劃優(yōu)化問(wèn)題,再加上 MySQL 特有的 SQL 與 Storage 分層架構(gòu)方式,造成了其性能比較低下,很多時(shí)候使用 union all 或者是union(必要的時(shí)候)的方式來(lái)代替“or”會(huì)得到更好的效果。
7.盡量用 union all 代替 union union 和 union all 的差異主要是前者需要將兩個(gè)(或者多個(gè))結(jié)果集合并后再進(jìn)行唯一性過(guò)濾操作,這就會(huì)涉及到排序,增加大量的 CPU 運(yùn)算,加大資源消耗及延遲。所以當(dāng)我們可以確認(rèn)不可能出現(xiàn)重復(fù)結(jié)果集或者不在乎重復(fù)結(jié)果集的時(shí)候,盡量使用 union all 而不是 union。
8.盡量早過(guò)濾 這一優(yōu)化策略其實(shí)最常見于索引的優(yōu)化設(shè)計(jì)中(將過(guò)濾性更好的字段放得更靠前)。 在 SQL 編寫中同樣可以使用這一原則來(lái)優(yōu)化一些 Join 的 SQL。
比如我們?cè)诙鄠€(gè)表進(jìn)行分頁(yè)數(shù)據(jù)查詢的時(shí)候,我們最好是能夠在一個(gè)表上先過(guò)濾好數(shù)據(jù)分好頁(yè),然后再用分好頁(yè)的結(jié)果集與另外的表 Join,這樣可以盡可能多的減少不必要的 IO 操作,大大節(jié)省 IO 操作所消耗的時(shí)間。9.避免類型轉(zhuǎn)換 這里所說(shuō)的“類型轉(zhuǎn)換”是指 where 子句中出現(xiàn) column 字段的類型和傳入的參數(shù)類型不一致的時(shí)候發(fā)生的類型轉(zhuǎn)換:A:人為在column_name 上通過(guò)轉(zhuǎn)換函數(shù)進(jìn)行轉(zhuǎn)換 直接導(dǎo)致 MySQL(實(shí)際上其他數(shù)據(jù)庫(kù)也會(huì)有同樣的問(wèn)題)無(wú)法使用索引,如果非要轉(zhuǎn)換,應(yīng)該在傳入的參數(shù)上進(jìn)行轉(zhuǎn)換 B:由數(shù)據(jù)庫(kù)自己進(jìn)行轉(zhuǎn)換 如果我們傳入的數(shù)據(jù)類型和字段類型不一致,同時(shí)我們又沒(méi)有做任何類型轉(zhuǎn)換處理,MySQL 可能會(huì)自己對(duì)我們的數(shù)據(jù)進(jìn)行類型轉(zhuǎn)換操作,也可能不進(jìn)行處理而交由存儲(chǔ)引擎去處理,這樣一來(lái),就會(huì)出現(xiàn)索引無(wú)法使用的情況而造成執(zhí)行計(jì)劃問(wèn)題。
以上兩種情況在開發(fā)者因?yàn)槟撤N原因經(jīng)常會(huì)有,本來(lái)可以用到索引的結(jié)果類型不對(duì)沒(méi)有用到索引,或是因?yàn)轭愋筒粚?duì)又有越界的情況發(fā)生造成無(wú)法使用索引的情況,結(jié)果造成很嚴(yán)重的事故。10.優(yōu)先優(yōu)化高并發(fā)的 SQL,而不是執(zhí)行頻率低某些“大”SQL 對(duì)于破壞性來(lái)說(shuō),高并發(fā)的 SQL 總是會(huì)比低頻率的來(lái)得大,因?yàn)楦卟l(fā)的 SQL 一旦出現(xiàn)問(wèn)題,甚至不會(huì)給我們?nèi)魏未⒌臋C(jī)會(huì)就會(huì)將系統(tǒng)壓跨。
而對(duì)于一些雖然需要消耗大量 IO 而且響應(yīng)很慢的 SQL,由于頻率低,即使遇到,最多就是讓整個(gè)系統(tǒng)響應(yīng)慢一點(diǎn),但至少可能撐一會(huì)兒,讓我們有緩沖的機(jī)會(huì)。11.從全局出發(fā)優(yōu)化,而不是片面調(diào)整 SQL 優(yōu)化不能是單獨(dú)針對(duì)某一個(gè)進(jìn)行,而應(yīng)充分考慮系統(tǒng)中所有的 SQL,尤其是在通過(guò)調(diào)整索引優(yōu)化 SQL 的執(zhí)行計(jì)劃的時(shí)候,千萬(wàn)不能顧此失彼,因小失大。
12.盡可能對(duì)每一條運(yùn)行在數(shù)據(jù)庫(kù)中的SQL進(jìn)行 explain 優(yōu)化 SQL,需要做到心中有數(shù),知道。
下面我們要四種關(guān)于mysql教程數(shù)據(jù)表幾種有效優(yōu)化方法
哦,從而提高mysql數(shù)據(jù)庫(kù)教程在應(yīng)用方面的數(shù)據(jù)吞吐能力。
一、優(yōu)化表的數(shù)據(jù)類型
select * from tablename procedure analyse();
select * from tablename procedure analyse(16.265);
上面輸出一列信息,牟你數(shù)據(jù)表的字段提出優(yōu)化建義,
二、通過(guò)拆分表提高數(shù)據(jù)訪問(wèn)效率
拆分一是指針對(duì)表進(jìn)行拆分,如果是針對(duì)myisam類型的表進(jìn)行處理的話,可以有兩種拆分方法
1、是垂直拆分,把主要的與一些散放到一個(gè)表,然后把主要的和另外的列放在另一張表。
2、水平拆分方法,根據(jù)一列或多列的值把數(shù)據(jù)行放到兩個(gè)獨(dú)立的表中,水平拆分通常幾種情況。
表很大,拆分后可降低查詢時(shí)數(shù)據(jù)和索引的查詢速度,同時(shí)也降低了索引的層數(shù),提高查詢的速度。
表中的數(shù)據(jù)本來(lái)就有獨(dú)立性,表中分別記錄各個(gè)地區(qū)的數(shù)據(jù)或不同時(shí)期的數(shù)據(jù),特別是有些數(shù)據(jù)常用,廁國(guó)一些數(shù)據(jù)不常用的情況下,
需要把數(shù)據(jù)存放到多個(gè)不同的介質(zhì)上。
三、逆規(guī)范化
四、使用中間表優(yōu)化方法對(duì)于數(shù)據(jù)庫(kù)教程大的表,在進(jìn)行統(tǒng)計(jì)查詢時(shí)通常會(huì)比較慢的,并且還要考慮查詢是否會(huì)對(duì)在線應(yīng)用產(chǎn)生影響,通常這種情況下我們使用中間表可以提高查詢統(tǒng)計(jì)速度
(1).選取最適用的字段屬性,應(yīng)該盡量把字段設(shè)置為NOT NULL,這樣在將來(lái)執(zhí)行查詢的時(shí)候,數(shù)據(jù)庫(kù)不用去比較NULL值。
(2).使用連接(JOIN)來(lái)代替子查詢(Sub-Queries)
(3).使用聯(lián)合(UNION)來(lái)代替手動(dòng)創(chuàng)建的臨時(shí)表
(4).盡量少使用 LIKE 關(guān)鍵字和通配符
(5).使用事務(wù)和外鍵
或者
(1).數(shù)據(jù)庫(kù)設(shè)計(jì)方面,這是DBA和Architect的責(zé)任,設(shè)計(jì)結(jié)構(gòu)良好的數(shù)據(jù)庫(kù),必要的時(shí)候,去正規(guī)化(英文是這個(gè):denormalize,中文翻譯成啥我不知道),允許部分?jǐn)?shù)據(jù)冗余,避免JOIN操作,以提高查詢效率
(2).系統(tǒng)架構(gòu)設(shè)計(jì)方面,表散列,把海量數(shù)據(jù)散列到幾個(gè)不同的表里面.快慢表,快表只留最新數(shù)據(jù),慢表是歷史存檔.集群,主服務(wù)器Read & write,從服務(wù)器read only,或者N臺(tái)服務(wù)器,各機(jī)器互為Master
(3).(1)和(2)超越PHP Programmer的要求了,會(huì)更好,不會(huì)沒(méi)關(guān)系.檢查有沒(méi)有少加索引
(4).寫高效的SQL語(yǔ)句,看看有沒(méi)有寫低效的SQL語(yǔ)句,比如生成笛卡爾積的全連接啊,大量的Group By和order by,沒(méi)有l(wèi)imit等等.必要的時(shí)候,把數(shù)據(jù)庫(kù)邏輯封裝到DBMS端的存儲(chǔ)過(guò)程里面.緩存查詢結(jié)果,explain每一個(gè)sql語(yǔ)句
(5).所得皆必須,只從數(shù)據(jù)庫(kù)取必需的數(shù)據(jù),比如查詢某篇文章的評(píng)論數(shù),select count(*) 。 where article_id = 就可以了,不要先select * 。 where article_id = 然后msql_num_rows.只傳送必須的SQL語(yǔ)句,比如修改文章的時(shí)候,如果用戶只修改了標(biāo)題,那就update 。 set title = where article_id = 不要set content = (大文本)
(6).必要的時(shí)候用不同的存儲(chǔ)引擎.比如InnoDB可以減少死鎖.HEAP可以提高一個(gè)數(shù)量級(jí)的查詢速度
1) 數(shù)據(jù)庫(kù)設(shè)計(jì)方面設(shè)計(jì)結(jié)構(gòu)良好的數(shù)據(jù)庫(kù),必要的時(shí)候,去正規(guī)化允許部分?jǐn)?shù)據(jù)冗余,避免 JOIN 操作,以提高查詢效率2) 系統(tǒng)架構(gòu)設(shè)計(jì)方面,表散列,把海量數(shù)據(jù)散列到幾個(gè)不同的表里面。
快慢表,快表只留最新數(shù)據(jù),慢表是歷史存檔。集群,主服務(wù)器進(jìn)行讀寫,從服務(wù)器只讀,或者 N 臺(tái)服務(wù)器,各機(jī)器互為 Master3) 檢查有沒(méi)有少加索引4) 寫高效的 SQL 語(yǔ)句,減少低效的 SQL 語(yǔ)句,比如生成笛卡爾積的全連接,大量的 Group By 和 order by,limit 等等。
必要的時(shí)候,把數(shù)據(jù)庫(kù)邏輯封裝到 DBMS 端的存儲(chǔ)過(guò)程里面。緩存查詢結(jié)果,explain 每一個(gè) sql語(yǔ)句5) 必要的時(shí)候用不同的存儲(chǔ)引擎。
比如 InnoDB 可以減少死鎖, HEAP 可以提高一個(gè)數(shù)量級(jí)的查詢速度。
優(yōu)化方案:
主從同步+讀寫分離:
這個(gè)表在有設(shè)備條件的情況下,讀寫分離,這樣能減少很多壓力,而且數(shù)據(jù)穩(wěn)定性也能提高
縱向分表:
根據(jù)原則,每個(gè)表最多不要超過(guò)5個(gè)索引,縱向拆分字段,將部分字段拆到一個(gè)新表
通常我們按以下原則進(jìn)行垂直拆分:(先區(qū)分這個(gè)表中的冷熱數(shù)據(jù)字段)
把不常用的字段單獨(dú)放在一張表;
把text,blob等大字段拆分出來(lái)放在附表中;
經(jīng)常組合查詢的列放在一張表中;
缺點(diǎn)是:很多邏輯需要重寫,帶來(lái)很大的工作量。
利用表分區(qū):
這個(gè)是推薦的一個(gè)解決方案,不會(huì)帶來(lái)重寫邏輯等,可以根據(jù)時(shí)間來(lái)進(jìn)行表分區(qū),相當(dāng)于在同一個(gè)磁盤上,表的數(shù)據(jù)存在不同的文件夾內(nèi),能夠極大的提高查詢速度。
橫向分表:
1000W條數(shù)據(jù)不少的,會(huì)帶來(lái)一些運(yùn)維壓力,備份的時(shí)候,單表備份所需時(shí)間會(huì)很長(zhǎng),所以可以根據(jù)服務(wù)器硬件條件進(jìn)行水平分表,每個(gè)表有多少數(shù)據(jù)為準(zhǔn)。
#1: 使用索引 MySQL允許對(duì)數(shù)據(jù)庫(kù)表進(jìn)行索引,以此能迅速查找記錄,而無(wú)需一開始就掃描整個(gè)表,由此顯著地加快查詢速度。
每個(gè)表最多可以做到16個(gè)索引,此外MySQL還支持多列索引及全文檢索。 給表添加一個(gè)索引非常簡(jiǎn)單,只需調(diào)用一個(gè)CREATE INDEX命令并為索引指定它的域即可。
列表A給出了一個(gè)例子:列表 Amysql> CREATE INDEX idx_username ON users(username);Query OK, 1 row affected (0。15 sec)Records: 1 Duplicates: 0 Warnings: 0 這里,對(duì)users表的username域做索引,以確保在WHERE或者HAVING子句中引用這一域的SELECT查詢語(yǔ)句運(yùn)行速度比沒(méi)有添加索引時(shí)要快。
通過(guò)SHOW INDEX命令可以查看索引已被創(chuàng)建(列表B)。列表 Bmysql> SHOW INDEX FROM users;--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment |--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+| users | 1 | idx_username | 1 | username | A | NULL | NULL | NULL | YES | BTREE | |--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+1 row in set (0。
00 sec) 值得注意的是:索引就像一把雙刃劍。對(duì)表的每一域做索引通常沒(méi)有必要,且很可能導(dǎo)致運(yùn)行速度減慢,因?yàn)橄虮碇胁迦牖蛐薷臄?shù)據(jù)時(shí),MySQL不得不每次都為這些額外的工作重新建立索引。
另一方面,避免對(duì)表的每一域做索引同樣不是一個(gè)非常好的主意,因?yàn)樵谔岣卟迦胗涗浀乃俣葧r(shí),導(dǎo)致查詢操作的速度減慢。 這就需要找到一個(gè)平衡點(diǎn),比如在設(shè)計(jì)索引系統(tǒng)時(shí),考慮表的主要功能(數(shù)據(jù)修復(fù)及編輯)不失為一種明智的選擇。
#2: 優(yōu)化查詢性能 在分析查詢性能時(shí),考慮EXPLAIN關(guān)鍵字同樣很管用。EXPLAIN關(guān)鍵字一般放在SELECT查詢語(yǔ)句的前面,用于描述MySQL如何執(zhí)行查詢操作、以及MySQL成功返回結(jié)果集需要執(zhí)行的行數(shù)。
下面的一個(gè)簡(jiǎn)單例子可以說(shuō)明(列表C)這一過(guò)程:列表 Cmysql> EXPLAIN SELECT city。name, city。
district FROM city, country WHERE city。countrycode = country。
code AND country。code = 'IND';+----+-------------+---------+-------+---------------+---------+---------+-------+------+-------------+| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |+----+-------------+---------+-------+---------------+---------+---------+-------+------+-------------+| 1 | SIMPLE | country | const | PRIMARY | PRIMARY | 3 | const | 1 | Using index || 1 | SIMPLE | city | ALL | NULL | NULL | NULL | NULL | 4079 | Using where |+----+-------------+---------+-------+---------------+---------+---------+-------+------+-------------+2 rows in set (0。
00 sec)這里查詢是基于兩個(gè)表連接。EXPLAIN關(guān)鍵字描述了MySQL是如何處理連接這兩個(gè)表。
必須清楚的是,當(dāng)前設(shè)計(jì)要求MySQL處理的是country表中的一條記錄以及city表中的整個(gè)4019條記錄。這就意味著,還可使用其他的優(yōu)化技巧改進(jìn)其查詢方法。
例如,給city表添加如下索引(列表D):列表 Dmysql> CREATE INDEX idx_ccode ON city(countrycode);Query OK, 4079 rows affected (0。15 sec)Records: 4079 Duplicates: 0 Warnings: 0現(xiàn)在,當(dāng)我們重新使用EXPLAIN關(guān)鍵字進(jìn)行查詢時(shí),我們可以看到一個(gè)顯著的改進(jìn)(列表E):列表 Emysql> EXPLAIN SELECT city。
name, city。district FROM city, country WHERE city。
countrycode = country。code AND country。
code = 'IND';+----+-------------+---------+-------+---------------+-----------+---------+-------+------+-------------+| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |+----+-------------+---------+-------+---------------+-----------+---------+-------+------+-------------+| 1 | SIMPLE | country | const | PRIMARY | PRIMARY | 3 | const | 1 | Using index || 1 | SIMPLE | city | ref | idx_ccode | idx_ccode | 3 | const | 333 | Using where |+----+-------------+---------+-------+---------------+-----------+---------+-------+------+-------------+2 rows in set (0。 01 sec) 在這個(gè)例子中,MySQL現(xiàn)在只需要掃描city表中的333條記錄就可產(chǎn)生一個(gè)結(jié)果集,其掃描記錄數(shù)幾乎減少了90%!自然,數(shù)據(jù)庫(kù)資源的查詢速度更快,效率更高。
#3: 調(diào)整內(nèi)部變量 MySQL是如此的開放,所以可輕松地進(jìn)一步調(diào)整其缺省設(shè)置以獲得更優(yōu)的性能及穩(wěn)定性。 需要優(yōu)化的一些關(guān)鍵變量如下:改變索引緩沖區(qū)長(zhǎng)度(key_buffer) 一般,該變量控制緩沖區(qū)的長(zhǎng)度在處理索引表(讀/寫操作)時(shí)使用。
MySQL使用手冊(cè)指出該變量可以不斷增加以確保索引表的最佳性能,并推薦使用與系統(tǒng)內(nèi)存25%的大小作為該變量的值。 這是MySQL十分重要的配置變量之一,如果你對(duì)優(yōu)化和提高系統(tǒng)性能有興趣,可以從改變key_buffer_size變量的值開始。
改變表長(zhǎng)(read_buffer_size) 當(dāng)一個(gè)查詢不斷地掃描某一個(gè)表,MySQL會(huì)為它分配一段內(nèi)存緩沖區(qū)。read_buffer_size變量控制這一緩沖區(qū)的大小。
如果你認(rèn)為連續(xù)掃描進(jìn)行得太慢,可以。
聲明:本網(wǎng)站尊重并保護(hù)知識(shí)產(chǎn)權(quán),根據(jù)《信息網(wǎng)絡(luò)傳播權(quán)保護(hù)條例》,如果我們轉(zhuǎn)載的作品侵犯了您的權(quán)利,請(qǐng)?jiān)谝粋€(gè)月內(nèi)通知我們,我們會(huì)及時(shí)刪除。
蜀ICP備2020033479號(hào)-4 Copyright ? 2016 學(xué)習(xí)鳥. 頁(yè)面生成時(shí)間:3.701秒