日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

索引快速查询

發布時間:2023/12/10 编程问答 21 豆豆
生活随笔 收集整理的這篇文章主要介紹了 索引快速查询 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一、索引

索引是表的目錄,在查找內容之前可以先在目錄中查找索引位置,以此快速定位查詢數據。對于索引,會保存在額外的文件中。

名詞:
?????覆蓋索引:
??????- 在索引文件中直接獲取數據
?????
?????索引合并:
??????- 把多個單列索引文件合并使用???

無索引:從前到后依次查找索引:id 創建索引文件(某種格式存儲)name 創建索引文件(某種格式存儲)email 創建索引文件(某種格式存儲) create index ix_name on userinfo3(email);name email 創建額外文件(某種格式存儲) 查詢時先在創建的索引文件內找到數據的定位,然后去原表內定位查找 索引種類(某種格式存儲):hash索引:索引文件表內的數據順序和表內的數據順序不一致,是根據hash值排列的,然后對應相應的內存位置,然后在返回原表內查找 單值查找速度快范圍查找速度慢btree索引:二叉樹的數據結構范圍查找速度快

MySQL中常見索引有:

  • 普通索引
  • 唯一索引
  • 主鍵索引
  • 組合索引

1、普通索引

普通索引僅有一個功能:加速查詢

create table in1(nid int not null auto_increment primary key,name varchar(32) not null, email varchar(64) not null, extra text, index ix_name (name) --普通索引,索引名(索引列) ) 創建表 + 索引

創建索引

create index 索引名稱 on 表名(列名)

刪除索引

drop index 索引名稱 on 表名

查看索引

show index from table_name;

注意:對于創建索引時如果是BLOB 和 TEXT 類型,必須指定length。

create index ix_extra on in1(extra(32)); View Code

2、唯一索引

唯一索引有兩個功能:加速查詢 和 唯一約束(可含null)

create table in1(nid int not null auto_increment primary key,name varchar(32) not null, email varchar(64) not null, extra text, unique ix_name (name) ) 創建表 + 唯一索引

創建:

create unique index 索引名稱 on 表名(列名)

刪除:

drop unique index 索引名稱 on 表名

3、主鍵索引

主鍵有兩個功能:加速查詢 和 唯一約束(不可含null)

create table in1(nid int not null auto_increment primary key,name varchar(32) not null, email varchar(64) not null, extra text, index ix_name (name) ) OR create table in1( nid int not null auto_increment, name varchar(32) not null, email varchar(64) not null, extra text, primary key(ni1), index ix_name (name) ) 創建表 + 創建主鍵

創建:

alter table 表名 add primary key(列名);

刪除:

alter table 表名 drop primary key; (刪除表的主鍵)

alter table 表名? modify? 列名 int, drop primary key;(刪除表指定列的主鍵)

4、組合索引

組合索引是將n個列組合成一個索引

- create unique index 索引名稱 on 表名(列名,列名)
- drop unique index 索引名稱 on 表名

其應用場景為:頻繁的同時使用n列來進行查詢,如:where n1 = 'alex' and n2 = 666。

create table in3(nid int not null auto_increment primary key,name varchar(32) not null, email varchar(64) not null, extra text ) 創建表 create index ix_name_email on in3(name,email); 創建組合索引

如上創建組合索引之后,查詢(最左前綴匹配):(name,email)

  • name and email? -- 使用索引
  • name???????????????? -- 使用索引
  • email???????????????? -- 不使用索引

注意:對于同時搜索n個條件時,組合索引的性能好于多個單一索引合并。

組合索引 - (name,email)select * from userinfo3 where name='alex' and email='asdf';select * from userinfo3 where name='alex';索引合并:- name- emailselect * from userinfo3 where name='alex' and email='asdf';select * from userinfo3 where name='alex';select * from userinfo3 where email='alex'; 組合索引和索引合并

5、全文索引:對文本的內容進行分詞,進行搜索

?二、相關命令

- 查看表結構desc 表名- 查看生成表的SQLshow create table 表名- 查看索引show index from 表名

三、正確使用索引

數據庫表中添加索引后確實會讓查詢速度起飛,但前提必須是正確的使用索引來查詢,如果以錯誤的方式使用,則即使建立索引也會不奏效。 ??? 即使建立索引,索引也不會生效:

id,enail創建索引- like '%xx' 沒有命中索引 select * from tb1 where email like '%cn'; - 使用函數select * from tb1 where reverse(email) = 'wupeiqi'; - orselect * from tb1 where nid = 1 or name = 'seven@live.com'; 無法命中索引(name列沒有建立索引) 特別的:當or條件中有未建立索引的列才失效,以下會走索引select * from tb1 where nid = 1 or name = 'seven@live.com' and email = 'alex'忽略name列(沒有創建索引)- 類型不一致如果列是字符串類型,傳入條件是必須用引號引起來,不然無法命中 select * from tb1 where email = 999;- !=select * from tb1 where email != 'alex'特別的:如果是主鍵,則還是會走索引select * from tb1 where nid != 123- >select * from tb1 where email > 'alex' 特別的:如果是主鍵或索引是整數類型,則還是會走索引select * from tb1 where nid > 123select * from tb1 where num > 123- order byselect name from tb1 order by email desc; (映射的是name列,所以不走索引)當根據索引排序時候,選擇的映射如果不是索引,則不走索引特別的:如果對主鍵排序,則還是走索引:select * from tb1 order by nid desc;- 組合索引最左前綴如果組合索引為:(name,email)name and email -- 使用索引name -- 使用索引email -- 不使用索引

四、其他注意事項

- 避免使用select *- count(1)或count(列) 代替 count(*)- 創建表時盡量時 char 代替 varchar- 表的字段順序固定長度的字段優先- 組合索引代替多個單列索引(經常使用多個條件查詢時)- 盡量使用短索引- 使用連接(JOIN)來代替子查詢(Sub-Queries)- 連表時注意條件類型需一致- 索引散列值(重復少)不適合建索引,例:性別不適合

五、limit分頁

無論是否有索引,limit分頁是一個值得關注的問題

a. select * from userinfo3 limit 20,10; b. - 不讓看(只能查看200頁)- 索引表中掃:1select * from userinfo3 where id in(select id from userinfo3 limit 200000,10) 不是最優答案2、最優解決方案:記錄當前頁最大或最小ID1. 頁面只有上一頁,下一頁# max_id# min_id下一頁數據:select * from userinfo3 where id > max_id limit 10;上一頁數據:select * from userinfo3 where id < min_id order by id desc limit 10; id倒序速度很快2. 上一頁 192 193 [196] 197 198 199 下一頁 基于當前的頁面,點擊其他任一頁分頁select * from userinfo3 where id in (select id from (select id from userinfo3 where id > max_id limit 30) as N order by N.id desc limit 10) c.id不連續,所以無法直接使用id范圍進行查找 between ... and

六、執行計劃

explain + 查詢SQL - 用于顯示SQL執行信息參數,根據參考信息可以進行SQL優化

讓mysql預估執行操作(一般正確)

mysql> explain select * from tb2; +----+-------------+-------+------+---------------+------+---------+------+------+-------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-------+------+---------------+------+---------+------+------+-------+ | 1 | SIMPLE | tb2 | ALL | NULL | NULL | NULL | NULL | 2 | NULL | +----+-------------+-------+------+---------------+------+---------+------+------+-------+ 1 row in set (0.00 sec) 查詢順序標識如:mysql> explain select * from (select nid,name from tb1 where nid < 10) as B;+----+-------------+------------+-------+---------------+---------+---------+------+------+-------------+| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |+----+-------------+------------+-------+---------------+---------+---------+------+------+-------------+| 1 | PRIMARY | <derived2> | ALL | NULL | NULL | NULL | NULL | 9 | NULL || 2 | DERIVED | tb1 | range | PRIMARY | PRIMARY | 8 | NULL | 9 | Using where |+----+-------------+------------+-------+---------------+---------+---------+------+------+-------------+特別的:如果使用union連接氣值可能為nullselect_type查詢類型SIMPLE 簡單查詢PRIMARY 最外層查詢SUBQUERY 映射為子查詢DERIVED 子查詢UNION 聯合UNION RESULT 使用聯合的結果...table正在訪問的表名type查詢時的訪問方式,性能:all < index < range < index_merge < ref_or_null < ref < eq_ref < system/constALL 全表掃描,對于數據表從頭到尾找一遍select * from tb1;特別的:如果有limit限制,則找到之后就不在繼續向下掃描select * from tb1 where email = 'seven@live.com'select * from tb1 where email = 'seven@live.com' limit 1;雖然上述兩個語句都會進行全表掃描,第二句使用了limit,則找到一個后就不再繼續掃描。INDEX 全索引掃描,對索引從頭到尾找一遍select nid from tb1;RANGE 對索引列進行范圍查找select * from tb1 where name < 'alex';PS:between andin> >= < <= 操作注意:!= 和 > 符號INDEX_MERGE 合并索引,使用多個單列索引搜索select * from tb1 where name = 'alex' or nid in (11,22,33);REF 根據索引查找一個或多個值select * from tb1 where name = 'seven';EQ_REF 連接時使用primary key 或 unique類型select tb2.nid,tb1.name from tb2 left join tb1 on tb2.nid = tb1.nid;CONST 常量表最多有一個匹配行,因為僅有一行,在這行的列值可被優化器剩余部分認為是常數,const表很快,因為它們只讀取一次。select nid from tb1 where nid = 2 ;SYSTEM 系統表僅有一行(=系統表)。這是const聯接類型的一個特例。select * from (select nid from tb1 where nid = 1) as A;possible_keys可能使用的索引key真實使用的key_lenMySQL中使用索引字節長度rowsmysql估計為了找到所需的行而要讀取的行數 ------ 只是預估值extra該列包含MySQL解決查詢的詳細信息“Using index”此值表示mysql將使用覆蓋索引,以避免訪問表。不要把覆蓋索引和index訪問類型弄混了。“Using where”這意味著mysql服務器將在存儲引擎檢索行后再進行過濾,許多where條件里涉及索引中的列,當(并且如果)它讀取索引時,就能被存儲引擎檢驗,因此不是所有帶
where子句的查詢都會顯示“Using
where”。有時“Using where”的出現就是一個暗示:查詢可受益于不同的索引。“Using temporary”這意味著mysql在對查詢結果排序時會使用一個臨時表。“Using filesort”這意味著mysql會對結果使用一個外部索引排序,而不是按索引次序從表里讀取行。mysql有兩種文件排序算法,這兩種排序方式都可以在內存或者磁盤上完成,
explain不會告訴你mysql將使用哪一種文件排序,也不會告訴你排序會在內存里還是磁盤上完成。“Range
checked for each record(index map: N)”這個意味著沒有好用的索引,新的索引將在聯接的每一行上重新估算,N是顯示在possible_keys列中索引的位圖,并且是冗余的。

?

七、慢日志查詢

a、配置MySQL自動記錄慢日志

slow_query_log = OFF 是否開啟慢日志記錄 long_query_time = 2 時間限制,超過此時間,則記錄 slow_query_log_file = /usr/slow.log     日志文件 log_queries_not_using_indexes = OFF     未使用索引的搜索是否記錄

?

配置:- 在內存中修改查看當前配置信息:
show variables like
'%query%' 查看慢日志配置
show variables like
'%querise%' 查看未使用索引的搜索是否記錄
     修改當前配置信息:
set global 變量名 =- 在配置文件中修改在終端啟動時輸入命令啟動配置文件mysqld --defaults-file=“配置文件路徑” 創建my.conf配置文件:slow_query_log = ON slow_query_log_file = D:/....注意:修改配置文件之后,先備份,再重啟服務

?

?

?

?

  

?

轉載于:https://www.cnblogs.com/domestique/p/6994863.html

總結

以上是生活随笔為你收集整理的索引快速查询的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。