1. 程式人生 > >Python學習 Day 056 - MySql - 索引

Python學習 Day 056 - MySql - 索引

主要內容;

  • 1.索引介紹
  • 2.常見的幾種索引
  • 3.索引名詞
  • 4.最左字首
  • 5.正確使用索引
  • 6.索引的注意事項
  • 7.執行計劃

1.索引介紹

資料庫中專門用於幫助使用者快速查詢資料的一種資料結構。類似於字典中的目錄,查詢字典內容時可以根據目錄查詢到資料的存放位置嗎,然後直接獲取。

索引的作用:約束和加速查詢

2.常見的幾種索引

- 普通索引
- 唯一索引
- 主鍵索引
- 聯合索引(多列)

   - 聯合主鍵索引 

  - 聯合唯一索引   
   - 聯合普通索引
無索引: 從前往後一條一條查詢
有索引:建立索引的本質,就是建立額外的檔案(某種格式儲存,查詢的時候,先去格外的檔案找,定好位置,然後再去原始表中直接查詢。但是建立索引越多,會對硬碟也是有損耗。

建立索引的目的:
a.額外的檔案儲存特殊的資料結構
b.查詢快,但是插入更新刪除依然慢
c.建立索引之後,必須命中索引才能有效

無索引和有索引的區別以及建立索引的目的
#索引的種類
hash索引和BTree索引
(1)hash型別的索引:查詢單條快,範圍查詢慢
(2)btree型別的索引:b+樹,層數越多,資料量指數級增長(我們就用它,因為innodb預設支援它

2.1 普通索引

#建立表 & 普通索引
create table userinfo(
                   nid int not null auto_increment primary key,
                   name varchar(32) not null,
                   email varchar(
64) not null, index ix_name(name) );
建立表&普通索引
#普通索引
create index 索引的名字 on 表名(列名)
#刪除索引
drop index 索引的名字 on 表名
#檢視索引
show index from 表名

2.2唯一索引

#建立表 & 唯一索引
  create table userinfo(
                   id int not null auto_increment primary key,
                   name varchar(
32) not null, email varchar(64) not null, unique index ix_name(name) );
建立表 &唯一索引
#唯一索引
create unique index 索引名 on 表名(列名)
#刪除唯一索引
drop index 索引名 on 表名;

2.3主鍵索引 (加速查詢和唯一約束)(不含null)

#主鍵索引
create table userinfo(

                   id int not null auto_increment primary key,
                   name varchar(32) not null,
                   email varchar(64) not null,
                   unique  index  ix_name(name)
           )
          or
           create table userinfo(
                   id int not null auto_increment,
                   name varchar(32) not null,
                   email varchar(64) not null,
                   primary key(nid),
                   unique  index  ix_name(name)
         )

建立表+主鍵索引
建立表和設定主鍵索引
# 主鍵索引
alter table 表名 add primary key(列名);
#刪除主鍵索引
alter table 表名 drop primary key;
alter table 表名  modify  列名 int, drop primary key;

2.4 組合索引

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

 其應用場景為:頻繁的同時使用n列來進行查詢,如:where name = 'alex' and email = '[email protected]'。

#聯合普通索引
create index 索引名 on 表名(列名1,列名2);

3.索引名詞

#覆蓋索引:在索引檔案中直接獲取資料
        例如:
        select name from userinfo where name = 'alex50000';

#索引合併:把多個單列索引合併成使用
        例如:
        select * from  userinfo where name = 'alex13131' and id = 13131;

4.最左字首

 

最左字首匹配:
        create index ix_name_email on user(name,email);
                 select * from userinfo where name = 'alex';
                 select * from userinfo where name = 'alex' and email='[email protected]';

                 select * from userinfo where  email='[email protected]';

             如果使用組合索引如上,name和email組合索引之後,查詢
             (1)name和email ---使用索引
             (2)name        ---使用索引
             (3)email       ---不適用索引
              對於同時搜尋n個條件時,組合索引的效能好於多個單列索引
        ******組合索引的效能>索引合併的效能*********

 

5.正確使用索引

 

  • 建立索引
  • 命中索引
  • 正確使用索引 (避免)
    - like '%xx'
                select * from userinfo where name like '%al';
            - 使用函式
                select * from userinfo where reverse(name) = 'alex333';
            - or
                select * from userinfo where id = 1 or email = '[email protected]';
                特別的:當or條件中有未建立索引的列才失效,以下會走索引
                        select * from userinfo where id = 1 or name = 'alex1222';
                        select * from userinfo where id = 1 or email = '[email protected]' and name = 'alex112'
            - 型別不一致
                如果列是字串型別,傳入條件是必須用引號引起來,不然...
                select * from userinfo where name = 999;
            - !=
                select count(*) from userinfo where name != 'alex'
                特別的:如果是主鍵,則還是會走索引
                    select count(*) from userinfo where id != 123
            - >
                select * from userinfo where name > 'alex'
                特別的:如果是主鍵或索引是整數型別,則還是會走索引
                    select * from userinfo where id > 123
                    select * from userinfo where num > 123
            - order by ***
                select email from userinfo order by name desc;
                當根據索引排序時候,選擇的對映如果不是索引,則不走索引
                特別的:如果對主鍵排序,則還是走索引:
                    select * from userinfo order by nid desc;
             
            - 組合索引最左字首
                如果組合索引為:(name,email)
                name and email       -- 使用索引
                name                 -- 使用索引
                email                -- 不使用索引

6.索引的注意事項

       (1)避免使用select *
       (2)count(1)或count(列) 代替count(*)
       (3)建立表時儘量使用char代替varchar
       (4)表的欄位順序固定長度的欄位優先
       (5)組合索引代替多個單列索引(經常使用多個條件查詢時)
       (6)儘量使用短索引 (create index ix_title on tb(title(16));特殊的資料型別 text型別)
       (7)使用連線(join)來代替子查詢
       (8)連表時注意條件型別需一致
       (9)索引雜湊(重複少)不適用於建索引,例如:性別不合適

7.執行計劃

 

select_type:
                查詢型別
                    SIMPLE          簡單查詢
                    PRIMARY         最外層查詢
                    SUBQUERY        對映為子查詢
                    DERIVED         子查詢
                    UNION           聯合
                    UNION RESULT    使用聯合的結果
table:
                正在訪問的表名
type:
查詢時的訪問方式,效能:all < index < range < index_merge < ref_or_null < ref < eq_ref < system/const
ALL  : 全表掃描,對於資料表從頭到尾找一遍 select * from userinfo;
       特別的:如果有limit限制,則找到之後就不在繼續向下掃描
           select * from userinfo where email = '[email protected]'
           select * from userinfo where email = '[email protected]' limit 1;
       雖然上述兩個語句都會進行全表掃描,第二句使用了limit,則找到一個後就不再繼續掃描。

INDEX :全索引掃描,對索引從頭到尾找一遍
                                select nid from userinfo;

RANGE:  對索引列進行範圍查詢
         select *  from userinfo where name < 'alex';
                                PS:
                                    between and
                                    in
                                    >   >=  <   <=  操作
                                    注意:!= 和 > 符號


INDEX_MERGE:  合併索引,使用多個單列索引搜尋
                                select *  from userinfo where name = 'alex' or nid in (11,22,33);

REF:       根據索引查詢一個或多個值
                                select *  from userinfo where name = 'alex112';

EQ_REF:    連線時使用primary key 或 unique型別
                                select userinfo2.id,userinfo.name from userinfo2 left join tuserinfo on userinfo2.id = userinfo.id;



CONST:常量
            表最多有一個匹配行,因為僅有一行,在這行的列值可被優化器剩餘部分認為是常數,const表很快,因為它們只讀取一次。
                 select id from userinfo where id = 2 ;

SYSTEM:系統
             表僅有一行(=系統表)。這是const聯接型別的一個特例。
                 select * from (select id from userinfo where id = 1) as A;


possible_keys:可能使用的索引

key:真實使用的

key_len:  MySQL中使用索引位元組長度

rows: mysql估計為了找到所需的行而要讀取的行數 ------ 只是預估值

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列中索引的點陣圖,並且是冗餘的

 

部落格參考:https://www.cnblogs.com/majj/p/9196025.html