MySQL索引與查詢(xún)優(yōu)化

MySQL Index

目錄

  • About MySQL
  • Why MySQL
  • MySQL Index
    • Why Index
    • 索引是如何工作的
    • 如何使用
      • 創(chuàng)建索引
      • 查看索引
      • 刪除索引
  • 索引的使用原則
    • 寫(xiě)操作比較頻繁的列慎重加索引
    • 索引越多占用磁盤(pán)空間越大
    • 不要為輸出列加索引
    • 考慮維度優(yōu)勢(shì)
    • 對(duì)短小的值加索引
    • 為字符串前綴加索引
    • 復(fù)合索引的左側(cè)索引
    • 索引加鎖
    • 覆蓋索引
    • 聚簇索引
    • 選擇合適的索引類(lèi)型
  • 查詢(xún)優(yōu)化建議
    • 使用explain分析查詢(xún)語(yǔ)句
      • select_type
      • type
      • Key
      • possible_keys
      • ref
      • rows
    • 聲明NOT NULL
    • 考慮使用數(shù)值類(lèi)型代替字符串
    • 考慮使用ENUM類(lèi)型
  • 總結(jié)
  • Links
    • 作者資源
    • 參考資料

About MySQL

MySQL(讀作/ma? ?si?kw?l/“My Sequel”)是一個(gè)開(kāi)放源碼的關(guān)系數(shù)據(jù)庫(kù)管理系統(tǒng),原開(kāi)發(fā)者為瑞典的MySQL AB公司,目前為Oracle旗下產(chǎn)品。

被甲骨文公司收購(gòu)后,自由軟件社群們對(duì)于Oracle是否還會(huì)持續(xù)支持MySQL社群版(MySQL之中唯一的免費(fèi)版本)有所隱憂(yōu),因此MySQL的創(chuàng)始人麥克爾·維德紐斯以MySQL為基礎(chǔ),成立分支計(jì)劃M(mǎn)ariaDB。原先一些使用MySQL的開(kāi)源軟件,部分轉(zhuǎn)向了MariaDB或其它的數(shù)據(jù)庫(kù)。

不可否認(rèn)的是,MySQL由于其性能高、成本低、可靠性好,已經(jīng)成為最流行的開(kāi)源數(shù)據(jù)庫(kù)之一,隨著MySQL的不斷成熟,它也逐漸用于更多大規(guī)模網(wǎng)站和應(yīng)用,非常流行的開(kāi)源軟件組合LAMP中的“M”指的就是MySQL。

Why MySQL

在眾多開(kāi)源免費(fèi)的關(guān)系型數(shù)據(jù)庫(kù)系統(tǒng)中,MySQL有以下比較出眾的優(yōu)勢(shì):

  1. 運(yùn)行速度快
  2. 易使用
  3. SQL語(yǔ)言支持
  4. 移植性好
  5. 功能豐富
  6. 成本低廉

對(duì)于其中運(yùn)行速度,根據(jù)官方介紹,MySQL 8.0 比之前廣泛使用的版本 MySQL 5.7 有了兩倍的提升。

image

在其官方的Benchmarks中,只讀的性能超過(guò)了每秒一百萬(wàn)次:

image

讀寫(xiě)的性能接近每秒二十五萬(wàn)次:

image

MySQL Index

Why Index

從概念上講,數(shù)據(jù)庫(kù)是數(shù)據(jù)表的集合,數(shù)據(jù)表是數(shù)據(jù)行和數(shù)據(jù)列的集合。當(dāng)你執(zhí)行一個(gè)SELECT語(yǔ)句從數(shù)據(jù)表中查詢(xún)部分?jǐn)?shù)據(jù)行的時(shí)候,得到的就是另外一個(gè)數(shù)據(jù)表和數(shù)據(jù)行的集合。

當(dāng)然,我們都希望獲得這個(gè)新的集合的時(shí)間盡可能地短,效率盡可能地高,這就是優(yōu)化查詢(xún)。

提升查詢(xún)速度的技術(shù)有很多,其中最重要的就是索引。當(dāng)你發(fā)現(xiàn)自己的查詢(xún)速度慢的時(shí)候,最快解決問(wèn)題的方法就是使用索引。索引的使用是影響查詢(xún)速度的重要因素。在使用索引之前其他的優(yōu)化查詢(xún)的動(dòng)作純粹是浪費(fèi)時(shí)間,只有合理地使用索引之后,才有必要考慮其他優(yōu)化方式。

索引是如何工作的

首先,在你的MySQL上創(chuàng)建t_user_action_log 表,方便下面進(jìn)行演示。

CREATE DATABASE `ijiangtao_local_db_mysql` /*!40100 DEFAULT CHARACTER SET utf8 */;

USE ijiangtao_local_db_mysql;

DROP TABLE IF EXISTS t_user_action_log;

CREATE TABLE `t_user_action_log` (
  `id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '主鍵id',
  `name` VARCHAR(32) DEFAULT NULL COMMENT '用戶(hù)名',
  `ip_address` VARCHAR(50) DEFAULT NULL COMMENT 'IP地址',
  `action` INT4 DEFAULT NULL COMMENT '操作:1-登錄,2-登出,3-購(gòu)物,4-退貨,5-瀏覽',
  `create_time` TIMESTAMP COMMENT '創(chuàng)建時(shí)間',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

INSERT INTO t_user_action_log (name, ip_address, `action`, create_time) values ('LiSi', '8.8.8.2', 1, CURRENT_TIMESTAMP);
INSERT INTO t_user_action_log (name, ip_address, `action`, create_time) values ('LiSi', '8.8.8.1', 2, CURRENT_TIMESTAMP);
INSERT INTO t_user_action_log (name, ip_address, `action`, create_time) values ('LiSi', '8.8.8.2', 1, CURRENT_TIMESTAMP);
INSERT INTO t_user_action_log (name, ip_address, `action`, create_time) values ('LiSi', '8.8.8.3', 1, CURRENT_TIMESTAMP);
INSERT INTO t_user_action_log (name, ip_address, `action`, create_time) values ('LiSi', '8.8.8.2', 2, CURRENT_TIMESTAMP);
INSERT INTO t_user_action_log (name, ip_address, `action`, create_time) values ('LiSi', '8.8.8.4', 1, CURRENT_TIMESTAMP);
INSERT INTO t_user_action_log (name, ip_address, `action`, create_time) values ('LiSi', '8.8.8.2', 2, CURRENT_TIMESTAMP);
INSERT INTO t_user_action_log (name, ip_address, `action`, create_time) values ('LiSi', '8.8.8.1', 1, CURRENT_TIMESTAMP);
INSERT INTO t_user_action_log (name, ip_address, `action`, create_time) values ('LiSi', '8.8.8.2', 2, CURRENT_TIMESTAMP);
INSERT INTO t_user_action_log (name, ip_address, `action`, create_time) values ('LiSi', '8.8.8.2', 1, CURRENT_TIMESTAMP);
INSERT INTO t_user_action_log (name, ip_address, `action`, create_time) values ('LiSi', '8.8.8.2', 3, CURRENT_TIMESTAMP);
INSERT INTO t_user_action_log (name, ip_address, `action`, create_time) values ('LiSi', '8.8.8.2', 5, CURRENT_TIMESTAMP);
INSERT INTO t_user_action_log (name, ip_address, `action`, create_time) values ('LiSi', '8.8.8.2', 2, CURRENT_TIMESTAMP);
INSERT INTO t_user_action_log (name, ip_address, `action`, create_time) values ('LiSi', '8.8.8.2', 2, CURRENT_TIMESTAMP);
INSERT INTO t_user_action_log (name, ip_address, `action`, create_time) values ('LiSi', '8.8.8.2', 3, CURRENT_TIMESTAMP);
INSERT INTO t_user_action_log (name, ip_address, `action`, create_time) values ('LiSi', '8.8.8.2', 3, CURRENT_TIMESTAMP);
INSERT INTO t_user_action_log (name, ip_address, `action`, create_time) values ('LiSi', '8.8.8.2', 5, CURRENT_TIMESTAMP);
INSERT INTO t_user_action_log (name, ip_address, `action`, create_time) values ('LiSi', '8.8.8.2', 3, CURRENT_TIMESTAMP);
INSERT INTO t_user_action_log (name, ip_address, `action`, create_time) values ('LiSi', '8.8.8.2', 3, CURRENT_TIMESTAMP);
INSERT INTO t_user_action_log (name, ip_address, `action`, create_time) values ('LiSi', '8.8.8.2', 4, CURRENT_TIMESTAMP);

假如我們要篩選 action2的所有記錄,SQL如下:

SELECT id, name, ip_address FROM t_user_action_log WHERE `action`=2;

通過(guò)查詢(xún)分析器explain分析這條查詢(xún)語(yǔ)句:

EXPLAIN SELECT id, name, ip_address FROM t_user_action_log WHERE `action`=2;

分析結(jié)果如下:

id select_type table partitions type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t_user_action_log ALL 1 100.00 Using where

其中typeALL表示要進(jìn)行全表掃描。這樣效率無(wú)疑是極慢的。

下面為action列添加索引:

ALTER TABLE t_user_action_log ADD INDEX (`action`);

然后再次執(zhí)行查詢(xún)分析,結(jié)果如下:

id select_type table partitions type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t_user_action_log ref action action 5 const 1 100.00

我們看到這次查詢(xún)就使用索引了。加索引前Extra的值是Using Where,加索引后Extra的值為空。

那么為什么索引會(huì)提高查詢(xún)速度呢?原因是索引會(huì)根據(jù)索引值進(jìn)行分類(lèi),這樣就不用再進(jìn)行全表掃描了。

image

比如上圖,action值為2的索引值分類(lèi)存儲(chǔ)在了索引空間,可以快速地查詢(xún)到索引值所對(duì)應(yīng)的列。

如何使用

下面介紹一下如何使用SQL創(chuàng)建、查看和刪除索引。

創(chuàng)建索引

三種方式:

  1. 使用CREATE INDEX創(chuàng)建,語(yǔ)法如下:
CREATE INDEX indexName ON tableName (columnName(length));

例如我們對(duì)ip_address這一列創(chuàng)建一個(gè)長(zhǎng)度為16的索引:

CREATE INDEX index_ip_addr ON t_user_action_log (ip_address(16));
  1. 使用ALTER語(yǔ)句創(chuàng)建,語(yǔ)法如下:
ALTER TABLE tableName ADD INDEX indexName(columnName);

ALTER語(yǔ)句創(chuàng)建索引前面已經(jīng)有例子了。下面提供一個(gè)設(shè)置索引長(zhǎng)度的例子:

ALTER TABLE t_user_action_log ADD INDEX ip_address_idx (ip_address(16));

SHOW INDEX FROM t_user_action_log;
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
t_user_action_log 1 ip_address_idx 1 ip_address A 1 16 YES BTREE
  1. 建表的時(shí)候創(chuàng)建索引:
CREATE TABLE tableName(  
  id INT NOT NULL,   
  columnName  columnType,
  INDEX [indexName] (columnName(length))  
);

查看索引

可以通過(guò)show語(yǔ)句查看索引:

SHOW INDEX FROM t_user_action_log;
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
t_user_action_log 0 PRIMARY 1 id A 199,368 BTREE
t_user_action_log 1 action 1 action A 4 YES BTREE
t_user_action_log 1 index_ip_addr 1 ip_address A 1 16 YES BTREE

刪除索引

使用ALTER命令可以刪除索引,例如:

ALTER TABLE t_user_action_log DROP INDEX index_ip_addr;

索引的使用原則

索引由于其提供的優(yōu)越的查詢(xún)性能,似乎不使用索引就是一個(gè)愚蠢的行為了。但是使用索引,是要付出時(shí)間和空間的代價(jià)的。因此,索引雖好不可貪多。

下面介紹幾個(gè)索引的使用技巧和原則,在使用索引之前,你應(yīng)該對(duì)它們有充分的認(rèn)識(shí)。

寫(xiě)操作比較頻繁的列慎重加索引

索引在提高查詢(xún)速度的同時(shí),也由于需要更新索引而帶來(lái)了降低插入、刪除和更新帶索引列的速度的問(wèn)題。一張數(shù)據(jù)表的索引越多,在寫(xiě)操作的時(shí)候性能下降的越厲害。

索引越多占用磁盤(pán)空間越大

與沒(méi)有加索引比較,加索引會(huì)更快地使你的磁盤(pán)接近使用空間極限。

不要為輸出列加索引

為查詢(xún)條件、分組、連接條件的列加索引,而不是為查詢(xún)輸出結(jié)果的列加索引。

例如下面的查詢(xún)語(yǔ)句:

select ip_address from t_user_action_log
where name='LiSi'
group by action
order by create_time;

所以可以考慮增加在 name action create_time 列上,而不是 ip_address。

考慮維度優(yōu)勢(shì)

例如action列的值包含:1、2、3、4、5,那么該列的維度就是5。

維度越高(理論上維度的最大值就是數(shù)據(jù)行的總數(shù)),數(shù)據(jù)列包含的獨(dú)一無(wú)二的值就越多,索引的使用效果越好。

對(duì)于維度很低的數(shù)據(jù)列,索引幾乎不會(huì)起作用,因此沒(méi)有必要加索引。

例如性別列的值只有男和女,每種查詢(xún)結(jié)果占比大約50%。一般當(dāng)查詢(xún)優(yōu)化處理器發(fā)現(xiàn)查詢(xún)結(jié)果超過(guò)全表的30%的時(shí)候,就會(huì)跳過(guò)索引,直接進(jìn)行全表掃描。

對(duì)短小的值加索引

對(duì)短小的值加索引,意味著索引所占的空間更小,可以減少I(mǎi)/O活動(dòng),同時(shí)比較索引的速度也更快。

尤其是主鍵,要盡可能短小。

另外,InnoDB使用的是聚集索引(clustered index),也就是把主鍵和數(shù)據(jù)行保存在一起。主鍵之外的其他索引都是二級(jí)索引,這些二級(jí)索引也保留著一份主鍵,這樣在查詢(xún)到索引以后,就可以根據(jù)主鍵找到對(duì)應(yīng)的數(shù)據(jù)行。如果主鍵太長(zhǎng)的話,會(huì)造成二級(jí)索引占用的空間變大。

比如下面的action索引保存了對(duì)應(yīng)行的id。

image

為字符串前綴加索引

前邊已經(jīng)講過(guò)短小索引的種種好處了,有時(shí)候一個(gè)字符串的前幾個(gè)字符就能唯一標(biāo)識(shí)這條記錄,這個(gè)時(shí)候設(shè)置索引的長(zhǎng)度就是非常劃算的做法。

前面已經(jīng)提供了設(shè)置索引length的例子,這里就不舉例子了。

復(fù)合索引的左側(cè)索引

創(chuàng)建復(fù)合索引的語(yǔ)法如下:

CREATE INDEX indexName ON tableName (column1 DESC, column2 DESC, column3 ASC);
image

我們可以看到,最左側(cè)的column1索引總是有效的。

索引加鎖

對(duì)于InnoDB來(lái)說(shuō),索引可以讓查詢(xún)鎖住更少的行,從而可以在并發(fā)情況下?lián)碛懈驯憩F(xiàn)。

下面演示一下查詢(xún)鎖與索引之間的關(guān)系。

前面使用的t_user_action_log表目前有一個(gè)id為主鍵,還有一個(gè)二級(jí)索引action。

下面這條語(yǔ)句的修改范圍是id值為1 2 3 4所在的行,查詢(xún)鎖會(huì)鎖住id值為1 2 3 4 5所在的行。

update ijiangtao_local_db_mysql.t_user_action_log set name='c1' where id<5;
  1. 首先創(chuàng)建數(shù)據(jù)庫(kù)連接1,開(kāi)啟事務(wù),并執(zhí)行update語(yǔ)句
set autocommit=0;

begin;

update ijiangtao_local_db_mysql.t_user_action_log set name='c1' where id<5;
  1. 然后開(kāi)啟另外一個(gè)連接2,分別執(zhí)行下面幾個(gè)update語(yǔ)句
-- 沒(méi)有被鎖
update ijiangtao_local_db_mysql.t_user_action_log set name='c2' where id=6;
-- 被鎖
update ijiangtao_local_db_mysql.t_user_action_log set name='c2' where id=5;

你會(huì)發(fā)現(xiàn)id=5的數(shù)據(jù)行已經(jīng)被鎖定,id=6的數(shù)據(jù)行可以正常提交。

  1. 連接1提交事務(wù),連接2的id=1id=5的數(shù)據(jù)行可以u(píng)pdate成功了。
-- 在連接1提交事務(wù)
commit;
mysql index lock
  1. 如果不使用索引

ip_address沒(méi)有索引的話,會(huì)鎖定全表。

連接1開(kāi)啟事務(wù)以后commit;之前,連接2對(duì)該表的update全部需要等待連接1釋放鎖。

set autocommit=0;

begin;

update ijiangtao_local_db_mysql.t_user_action_log set name='c1' where ip_address='8.8.8.1';
mysql index lock

覆蓋索引

如果索引包含滿(mǎn)足查詢(xún)的所有數(shù)據(jù),就被稱(chēng)為覆蓋索引(Covering Indexes),覆蓋索引非常強(qiáng)大,可以大大提高查詢(xún)性能。

覆蓋索引高性能的原因是:

  • 索引通常比記錄要小,覆蓋索引查詢(xún)只需要讀索引,而不需要讀記錄。
  • 索引都按照值的大小進(jìn)行順序存儲(chǔ),相比與隨機(jī)訪問(wèn)記錄,需要更少的I/0。
  • 大多數(shù)數(shù)據(jù)引擎能更好的緩存索引,例如MyISAM只緩存索引。

ijiangtao_local_db_mysql表的action列包含索引。使用explain分析下面的查詢(xún)語(yǔ)句,對(duì)于索引覆蓋查詢(xún)(index-covered query),分析結(jié)果Extra的值是Using index,表示使用了覆蓋索引 :

explain select `action` from ijiangtao_local_db_mysql.t_user_action_log;
id select_type table partitions type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t_user_action_log index action 5 199,703 100.00 Using index

聚簇索引

聚簇索引(Clustered Indexes)保證關(guān)鍵字的值相近的元組存儲(chǔ)的物理位置也相同,且一個(gè)表只能有一個(gè)聚簇索引。

字符串類(lèi)型不建議使用聚簇索引,特別是隨機(jī)字符串,因?yàn)樗鼈儠?huì)使系統(tǒng)進(jìn)行大量的移動(dòng)操作。

并不是所有的存儲(chǔ)引擎都支持聚簇索引,目前InnoDB支持。

如果使用聚簇索引,最好使用AUTO_INCREMENT列作為主鍵,應(yīng)該盡量避免使用隨機(jī)的聚簇主鍵。

從物理位置上看,聚簇索引表比非聚簇的索引表,有更好的訪問(wèn)性能。

聚簇索引與非聚簇索引

選擇合適的索引類(lèi)型

從數(shù)據(jù)結(jié)構(gòu)角度來(lái)看,MySQL支持的索引類(lèi)型有B樹(shù)索引、Hash索引等。

  • B樹(shù)索引

B樹(shù)索引對(duì)于<、<=、 =、 >=、 >、 <>、!=、 between查詢(xún),進(jìn)行精確比較操作和范圍比較操作都有比較高的效率。

B樹(shù)索引也是InnoDB存儲(chǔ)引擎默認(rèn)的索引結(jié)構(gòu)。

  • Hash索引

Hash索引僅能滿(mǎn)足=、<=>、in查詢(xún)。

Hash索引檢索效率非常高,索引的檢索可以一次定位,不像B樹(shù)索引需要從根節(jié)點(diǎn)到枝節(jié)點(diǎn),最后才能訪問(wèn)到頁(yè)節(jié)點(diǎn)這樣多次的I/O訪問(wèn),所以Hash索引的查詢(xún)效率要遠(yuǎn)高于B樹(shù)索引。但Hash索引不能使用范圍查詢(xún)。

查詢(xún)優(yōu)化建議

下面提供幾個(gè)查詢(xún)優(yōu)化的建議。

使用explain分析查詢(xún)語(yǔ)句

前面已經(jīng)演示過(guò)如何使用explain命令分析查詢(xún)語(yǔ)句了,這里再解釋一下其中幾個(gè)有參考價(jià)值的字段的含義:

select_type

select_type表示查詢(xún)中每個(gè)select子句的類(lèi)型,一般有下面幾個(gè)值:

  • SIMPLE
    簡(jiǎn)單SELECT,不使用UNION或子查詢(xún)等。

  • PRIMARY
    查詢(xún)中若包含任何復(fù)雜的子部分,最外層的select被標(biāo)記為PRIMARY。

  • UNION
    UNION中的第二個(gè)或后面的SELECT語(yǔ)句。

  • DEPENDENT UNION
    UNION中的第二個(gè)或后面的SELECT語(yǔ)句,取決于外面的查詢(xún)。

  • UNION RESULT
    UNION的結(jié)果。

  • SUBQUERY
    子查詢(xún)中的第一個(gè)SELECT。

  • DEPENDENT SUBQUERY
    子查詢(xún)中的第一個(gè)SELECT,取決于外面的查詢(xún)。

  • DERIVED
    派生表的SELECT, FROM子句的子查詢(xún)。

  • UNCACHEABLE SUBQUERY
    一個(gè)子查詢(xún)的結(jié)果不能被緩存,必須重新評(píng)估外鏈接的第一行。

type

type表示MySQL在表中找到所需行的方式,又稱(chēng)“訪問(wèn)類(lèi)型”,常用的類(lèi)型有:

ALL, index, range, ref, eq_ref, const, system, NULL。

從左到右,性能從差到好。

  • ALL:
    Full Table Scan,MySQL將遍歷全表以找到匹配的行。

  • index:
    Full Index Scan,index與ALL區(qū)別為index類(lèi)型只遍歷索引樹(shù)。

  • range:
    只檢索給定范圍的行,使用一個(gè)索引來(lái)選擇行。

  • ref:
    表示上述表的連接匹配條件,即哪些列或常量被用于查找索引列上的值。

  • eq_ref:
    類(lèi)似ref,區(qū)別就在使用的索引是唯一索引,對(duì)于每個(gè)索引鍵值,表中只有一條記錄匹配,簡(jiǎn)單來(lái)說(shuō),就是多表連接中使用primary key或者 unique key作為關(guān)聯(lián)條件。

  • const:
    當(dāng)MySQL對(duì)查詢(xún)某部分進(jìn)行優(yōu)化,并轉(zhuǎn)換為一個(gè)常量時(shí),使用這些類(lèi)型訪問(wèn)。
    如將主鍵置于where列表中,MySQL就能將該查詢(xún)轉(zhuǎn)換為一個(gè)常量。

  • NULL:
    MySQL在優(yōu)化過(guò)程中分解語(yǔ)句,執(zhí)行時(shí)甚至不用訪問(wèn)表或索引,例如從一個(gè)索引列里選取最小值可以通過(guò)單獨(dú)索引查找完成。

Key

key列顯示MySQL實(shí)際決定使用的鍵(索引),如果沒(méi)有選擇索引,鍵是NULL。

possible_keys

possible_keys指出MySQL能使用哪個(gè)索引在表中找到記錄,查詢(xún)涉及到的字段上如果存在索引則該索引將被列出,但不一定被查詢(xún)使用。

ref

ref表示上述表的連接匹配條件,即哪些列或常量被用于查找索引列上的值。

rows

rows表示MySQL根據(jù)表統(tǒng)計(jì)信息,以及索引選用的情況,找到所需記錄需要讀取的行數(shù)。這個(gè)行數(shù)是估算的值,實(shí)際行數(shù)可能不同。

聲明NOT NULL

當(dāng)數(shù)據(jù)列被聲明為NOT NULL以后,在查詢(xún)的時(shí)候就不需要判斷是否為NULL,由于減少了判斷,可以降低復(fù)雜性,提高查詢(xún)速度。

如果要表示數(shù)據(jù)列為空,可以使用0等代替。

考慮使用數(shù)值類(lèi)型代替字符串

MySQL對(duì)數(shù)值類(lèi)型的處理速度要遠(yuǎn)遠(yuǎn)快于字符串,而且數(shù)值類(lèi)型往往更加節(jié)省空間。

例如對(duì)于“Male”和“Female”可以用“0”和“1”進(jìn)行代替。

考慮使用ENUM類(lèi)型

如果你的數(shù)據(jù)列的取值是確定有限的,可以使用ENUM類(lèi)型代替字符串。因?yàn)镸ySQL會(huì)把這些值表示為一系列對(duì)應(yīng)的數(shù)字,這樣處理的速度會(huì)提高很多。

CREATE TABLE shirts (
    name VARCHAR(40),
    size ENUM('x-small', 'small', 'medium', 'large', 'x-large')
);

INSERT INTO shirts (name, size) VALUES ('dress shirt','large'), ('t-shirt','medium'),
  ('polo shirt','small');

SELECT name, size FROM shirts WHERE size = 'medium';

總結(jié)

索引是一個(gè)單獨(dú)的,存儲(chǔ)在磁盤(pán)上的數(shù)據(jù)結(jié)構(gòu),索引對(duì)數(shù)據(jù)表中一列或者多列值進(jìn)行排序,索引包含著對(duì)數(shù)據(jù)表中所有數(shù)據(jù)的引用指針。

本教程從MySQL開(kāi)始講起,又介紹了MySQL中索引的使用,最后提供了使用索引的幾條原則和優(yōu)化查詢(xún)的幾個(gè)方法。

無(wú)論你是DBA還是軟件開(kāi)發(fā),菜鳥(niǎo)程序員還是資深工程師,相信本節(jié)提到的關(guān)于索引的知識(shí),對(duì)你都會(huì)有所幫助。

Links

作者資源

參考資料

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容