MySQL—【加餐1】高效查询方法
高效查詢方法
隨著數(shù)據(jù)量的增大,企業(yè)對查詢的速度要求也越來越高,掌握高效查詢的方法對于平時的工作是非常有幫助的。下面我們就一起來看一下有哪些方法可以高效查詢。
為了提高數(shù)據(jù)的查詢速度,最常用的解決方案就是給表中變量創(chuàng)建索引。我們可以將索引理解成書的目錄,如果一本書沒有目錄,那檢索起來可能就比較麻煩,一旦有了目錄,我們就可以根據(jù)目錄進行索引,很快地找到我們需要的內(nèi)容。同樣的道理,如果數(shù)據(jù)表中有了索引,就可以大大提高MySQL的執(zhí)行效率。
1. 常見索引類型
索引有很多種類型,下面我們一起來學(xué)習(xí)幾個比較常用的索引類型。
(1)普通索引
普通索引是一種沒有任何約束的索引,它對表中變量的值不做任何的限制,不管變量的值是否存在重復(fù)值或缺失值(也就是NULL值),所以普通索引是使用最頻繁的一種索引。
可以通過兩種方式來建立普通索引:
- 創(chuàng)建新表時設(shè)定某個字段為普通索引
- 基于已有的表添加普通索引
以校園一卡通消費數(shù)據(jù)stu_card為例,查詢出交易時間在2013年9月1日的所有記錄。
# 沒有創(chuàng)建索引之前的條件查詢 SELECT * FROM stu_card WHERE custom_date BETWEEN '2013-09-01 00:00:00' AND '2013-09-01 23:59:59';結(jié)果顯示,1200萬行數(shù)據(jù),查詢出滿足條件的3萬多行數(shù)據(jù)大約需要14.907s的時間。
# 創(chuàng)建索引 CREATE INDEX date_index ON stu_card(custom_date); # 執(zhí)行查詢 SELECT * FROM stu_card WHERE custom_date BETWEEN '2013-09-01 00:00:00' AND '2013-09-01 23:59:59';結(jié)果顯示,基于普通索引的查詢代碼,獲取滿足條件的交易記錄只需要0.1秒左右,速度有明顯提升。
(2)唯一索引
相對于普通索引來說,唯一索引對字段或者字段組合是有約束的,也就是必選確保字段或者字段組合的每一個觀測值都是唯一的,不能存在重復(fù)值。如果字段中還有多個空白字符串,也算是有重復(fù)值,因為空字符串代表一種值。
一個表中可以有多個唯一索引,創(chuàng)建唯一索引的方法也有兩種,與創(chuàng)建普通索引類似。可以在創(chuàng)建新表的時候設(shè)置唯一索引,也可以對已有表添加唯一索引。
# 兩種唯一索引的創(chuàng)建方法 # 建表時創(chuàng)建索引 CREATE TABLE <table_name_> ( field1 data_type1, field2 data_type2, field3 data_type3, ……UNIQUE <index_name>(field1,field2)); # 對已有表添加索引,可以通過創(chuàng)建法或修改法 CREATE UNIQUE INDEX <index_name> ON <table_name_>(field_list); #基于已有的表創(chuàng)建索引 ALTER TABLE <table_name_> ADD UNIQUE <index_name> (field_list); #基于已有表修改索 引接下來以某平臺的旅游交易數(shù)據(jù)為例,對比無索引和基于唯一索引的兩種查詢的速度。
# 新建數(shù)據(jù)表tourism_orders CREATE TABLE tourism_orders( userid VARCHAR(20), orderid VARCHAR(12), orderTime VARCHAR(15), orderType VARCHAR(2), city VARCHAR(20), country VARCHAR(20), continent VARCHAR(10)); # 往表中插數(shù)據(jù) LOAD DATA local INFILE '/Users/zhucan/Desktop/tourism_orders.csv' INTO TABLE tourism_orders FIELDS TERMINATED BY ',' LINES TERMINATED BY '\n' IGNORE 1 ROWS; # 查詢數(shù)據(jù)前幾行 SELECT * FROM tourism_orders LIMIT 10; # 無索引下的條件查詢 SELECT * FROM tourism_orders WHERE userid = '100000001445'; # 約0.016秒 # 創(chuàng)建兩個組合變量的唯一索引 CREATE UNIQUE INDEX id_idx ON tourism_orders(userid, orderid); # 再次執(zhí)行查詢語句 SELECT * FROM tourism_orders WHERE userid = '100000001445'; # 幾乎為0秒(3)主鍵索引
主鍵索引對字段的要求最為嚴格,必須確保字段中的值既不存在重復(fù)值也不存在缺失值。與普通索引和唯一索引不同的是,一張表中只能有一個主鍵索引。關(guān)于主鍵索引的創(chuàng)建語法:
這里使用用戶注冊數(shù)據(jù)和用戶交易數(shù)據(jù),來驗證主鍵索引構(gòu)建前后查詢速度的差異。
# 創(chuàng)建用戶注冊表和RFM表 CREATE TABLE regit_info ( uid VARCHAR(10), gender TINYINT, age TINYINT, regit_date DATE ); CREATE TABLE RFM ( uid VARCHAR(10), R INT, F TINYINT, M DECIMAL(10,2) ); # 批量導(dǎo)入數(shù)據(jù) LOAD DATA local INFILE '/Users/zhucan/Desktop/regit_info.csv' INTO TABLE regit_info FIELDS TERMINATED BY ',' LINES TERMINATED BY '\n' IGNORE 1 ROWS; LOAD DATA local INFILE '/Users/zhucan/Desktop/RFM.csv' INTO TABLE RFM FIELDS TERMINATED BY ',' LINES TERMINATED BY '\n' IGNORE 1 ROWS; # 內(nèi)連接完成兩表字段的合并 SELECT t1.*,t2.R,t2.F,t2.M FROM regit_info AS t1 INNER JOIN RFM AS t2 ON t1.uid=t2.uid LIMIT 10000; # 添加主鍵索引 ALTER TABLE regit_info ADD PRIMARY key (uid); ALTER TABLE RFM ADD PRIMARY key (uid); # 再次執(zhí)行查詢 SELECT t1.*,t2.R,t2.F,t2.M FROM regit_info AS t1 INNER JOIN RFM AS t2 ON t1.uid=t2.uid2. 索引的查詢
如果想要對表進行操作,通常需要知道表中是否已經(jīng)存在索引,如果存在這些索引又是什么類型的,名稱是什么,是設(shè)置在哪些字段上了等等。只有了解表中的索引信息,我們才能進一步管理索引。
# 查詢索引信息語法 SHOW INDEX FROM <table_name_>;查詢用戶注冊表regit_info和旅游交易表tourism_orders的索引信息:
SHOW INDEX FROM regit_info; SHOW INDEX FROM tourism_orders;3. 刪除索引
# 刪除索引語法 DROP INDEX <index_name> ON <table_name_>; #用于刪除普通索引和唯一索引 ALTER TABLE <table_name_> DROP INDEX <index_name>; #用于刪除普通索引和唯一索引 ALTER TABLE <table_name_> DROP PRIMARY KEY; #用于刪除主鍵索引刪除用戶注冊表regit_info中的主鍵索引:
ALTER TABLE regit_info DROP PRIMARY KEY; #刪除索引 SHOW INDEX FROM regit_info; #查看索引刪除旅游交易表tourism_orders中的唯一索引:
DROP INDEX id_idx ON tourism_orders; #刪除索引 SHOW INDEX FROM tourism_orders; #查看索引4 . 關(guān)于索引的注意事項
盡管索引有提速的功能(可以提高響應(yīng)的select的效率),但是也不能濫用,因為它會降低數(shù)據(jù)表的寫操作速度(insert 和 update的效率會變低),也會占用一定的磁盤空間。所以在創(chuàng)建和使用索引的過程
中,有一些事項需要大家注意:
4.1 何時創(chuàng)建索引
- WHERE 關(guān)鍵詞后面的字段創(chuàng)建索引,可以加快條件判斷速度
- ORDER BY關(guān)鍵詞后面的字段創(chuàng)建索引,可以加快排序速度
- 表連接關(guān)鍵詞 ON 后面的字段創(chuàng)建索引,可以加快表連接速度
- 包含大量NULL的字段不適合創(chuàng)建索引,因為索引不可以包含NULL值
- 包含大量重復(fù)值的字段不適合創(chuàng)建索引,因為基于索引的查詢規(guī)則,在進行條件篩選的時候
- 可能會產(chǎn)生大量的數(shù)據(jù)行,此時索引并不能加快數(shù)據(jù)庫搜索過程中的掃描速度
4.2 索引無效的情況
- WHERE 關(guān)鍵詞后面的條件表達式中如果使用IN、OR、!=或者<>,均會導(dǎo)致索引無效。解決方法是將“!=”或者“<>”替換為">AND<",將"IS NOT NULL"替換為">=CHR(0)"。
- 篩選或排序過程中,如果對索引列使用函數(shù),則索引失效。
- 篩選過程中,如果字符型字段寫成了數(shù)值型的數(shù)字,則索引失效(比如,用戶id字段是字符型,那篩選的時候需要寫where uid = “1”)
- 使用模糊查詢的時候,如果將通配符放在開頭,則索引失效(like “%aaa%” 不會使用索引而like“aaa%”可以使用索引)
- 對于多列的組合索引,遵循左原則,例如對字段A,B,C設(shè)置索引 INDEX(A,B,C) ,則"A>0" “A=1 AND B>10”、“A=10 AND B<6 AND C>100"都可以使組合索引有效,但是"B>10”、"B<6 AND C>100"都會導(dǎo)致組合索引失效。
- 在JOIN操作中,關(guān)鍵詞ON后面的字段類型要保持一致(也就是左表中這個字段的數(shù)據(jù)類型和右表中同一字段的數(shù)據(jù)類型要保持一致),否則索引無效。
4.3 索引數(shù)量并不是越多越好
原則上,一個表的索引數(shù)量最好不要超過6個(當然也得看你的數(shù)據(jù)的原始字段個數(shù))
總結(jié)
以上是生活随笔為你收集整理的MySQL—【加餐1】高效查询方法的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: MySQL——数据库的增删改操作
- 下一篇: 数据库分区表的使用