1. 程式人生 > 實用技巧 >阿里的御用框架,MyBatis與設計模式的激情碰撞

阿里的御用框架,MyBatis與設計模式的激情碰撞

技術標籤:MySQLmysql

MySQL索引

  1. 定義

    1. 是資料庫管理系統中的一個排序資料結構,佔用一定的儲存空間,底層實現B樹
  2. 索引解決了什麼問題

    1. 資料表做資料查詢一般情況是全表掃描,資料量小的話,一千以下,時間消耗不大,如果資料量超過一千以上,效率開始以每千條增加1.3ms。索引可以極大地提高查詢效率,將查詢效能提升幾個數量級。索引原理:對資料分門別類縮小查詢範圍從而提高查詢效率。
  3. MySQL索引種類:主要有五種

    1. 主鍵索引(primary key)
      1. 特殊的唯一索引:唯一索引=主鍵索引+null 值
      2. 列的值必須唯一,不允許有重複值,不允許有空值
      3. 可以再建立表的時候直接指定,不能使用create index 建立,可以使用alter table 建立
    2. 唯一索引(unique )
      1. 與普通索引類似
      2. 不同的是索引的列值必須是唯一的,不能有重複值
      3. 列值可以允許有空值
      4. 如果是組合索引,列值的組合必須是唯一的
    3. 普通索引
      1. 最基本的索引,沒有任何限制
    4. 組合索引
      1. 普通索引+多列
    5. 全文索引(fulltext index)
      1. 全文FullText索引用於全文搜尋,只有InnoDB和MyiSAM儲存引擎支援全文索引
      2. 僅適用於char、varchar、text列
  4. 關於索引的幾個問題

    1. 建立索引的表的資料量需要有多大?

      1. 資料量超過一千條,才會看出索引效率

      2. region 是資料量為三千七條的表,bs_street 表資料四萬二

      3. select * from region where id = ‘310112’;–有索引時: 0.001s

        select * from region where id = ‘310112’; --無索引時: 0.005s

        select * from bs_street where street_id = ‘65537’; ## 有索引:0.001s 精準查詢+索引 select * from bs_street where street_id = ‘65537’; 沒有索引時:0.053s

        結論:每千條資料增加查詢時間1.3ms

    2. 表建立時預設為主鍵建立索引?

      1. 不是,只有使用primary key 定義了主鍵id,才會在主鍵id上建立索引primary key
    3. 在sql中建立sql語句驗證sql執行效率?

      1. 示列:name建立一個普通索引
        1. alter table region add index name_index(name);
        2. select * from region where name = ‘閔行區’;-- 0.001s
        3. 查詢效率一下子就提高了:-- 0.004s
    4. 建立專案驗證sql查詢效率?

      1. 有業務邏輯程式碼佔用時間,
      2. 對於表的操作增刪改查,是否擁有索引,效率檢視,直接在sql語句的執行時間就可以了
    5. 同一列上是否可以新增多種索引?

      1. alter table region add primary key (id) ;
        alter table region add unique (id) ;
        alter table region add index id_index (id);
        
      2. 上述sql執行成功,同一列上可以新增多種索引。

    6. 如果某列上有多個索引,查詢效果會疊加嗎?

      1. 不會,因為每條sql的查詢只能使用一個索引
      2. explain select * from region where id = ‘110115’
      3. id是主鍵索引、唯一索引、普通索引、生效的只有primary key
    7. 查詢中如果多個語句分別用到了索引,查詢的效率是否疊加?

      1. select * from region where id = (select id from region where name = ‘大興區’);–id無索引,name無索引,0.011s
      2. select * from region where id = (select id from region where name = ‘大興區’);–id有索引,name無索引,0.004s
      3. select * from region where id = (select id from region where name = ‘大興區’);–id有索引,name有索引,0.001s
      4. id 列是primary key 索引,name列是index 普通索引
      5. 查詢中每個都用到了單列索引,查詢的效率肯定是疊加的。
  5. 如何使用索引

    1. 建立索引

      1. CREATE INDEX INDEX_NAME ON TABLE_NAME (COLUMN)

        1. 不適用於主鍵索引primary key

          示例:create index name_index on region (name) ;

      2. 建立表時建立索引

        1. create table teacher(
          id int(10) not null ,
          name varchar(20) null,
          age int(3) null,
          address varchar(30) null,
          primary key (id)
          )
          
    2. 檢視索引

      1. show index from table_name ;

        示例:show index from region ;

      2. show keys from table_name ;

    3. 修改表結構時新增索引

      ​ 1.新增PRIMARY KEY(主鍵索引)

      ​ ALTER TABLE table_name ADD PRIMARY KEY ( column )

      ​ 2.新增UNIQUE(唯一索引)
      ​ ALTER TABLE table_name ADD UNIQUE ( column )

      ​ 3.新增INDEX(普通索引)

      ​ ALTER TABLE table_name ADD INDEX index_name ( column )

      ​ 4.新增FULLTEXT(全文索引)

      ​ ALTER TABLE table_name ADD FULLTEXT ( column)

      ​ 5.新增多列索引

      ​ ALTER TABLE table_name ADD INDEX index_name ( column1, column2, column3 )

      組合索引和普通索引,因為不是唯一的,所以需要指定索引名

      主鍵索引、唯一索引、全文索引,因為是唯一的,所以只需要指定索引型別就可以了

    4. 刪除索引

      1. drop index index_name on table_name ;

        1. 示例:DROP INDEX NAME_INDEX ON REGION ;
      2. alter table table_name drop index index_name ;

      3. alter table table_name drop primary key ;

        1. 示例:alter table region drop primary key ;
      4. [SQL]alter table region drop primary key ;
        受影響的行: 3750 時間: 4.576s

      5. 索引已經刪除了,再執行一次:alter table region drop primary key ;

        [SQL]alter table region drop primary key ;
        [Err] 1091 - Can’t DROP ‘PRIMARY’; check that column/key exists

    5. 驗證索引是否生效

      1. explain select * from region where id = ‘110115’ and name = ‘大興區’;
        • table:這是表的名字。
      • type:連線操作的型別。下面是MySQL文件關於ref連線型別的說明:

        “對於每一種與另一個表中記錄的組合,MySQL將從當前的表讀取所有帶有匹配索引值的記錄。如果連線操作只使用鍵的最左字首,或者如果鍵不是UNIQUE或PRIMARY KEY型別(換句話說,如果連線操作不能根據鍵值選擇出唯一行),則MySQL使用ref連線型別。如果連線操作所用的鍵只匹配少量的記錄,則ref是一種好的連線型別。”

        在本例中,由於索引不是UNIQUE型別,ref是我們能夠得到的最好連線型別。

        如果EXPLAIN顯示連線型別是“ALL”,而且你並不想從表裡面選擇出大多數記錄,那麼MySQL的操作效率將非常低,因為它要掃描整個表。你可以加入更多的索引來解決這個問題。預知更多資訊,請參見MySQL的手冊說明。

      • possible_keys:
        可能可以利用的索引的名字。這裡的索引名字是建立索引時指定的索引暱稱;如果索引沒有暱稱,則預設顯示的是索引中第一個列的名字(在本例中,它是“firstname”)。預設索引名字的含義往往不是很明顯。

      • Key:
        它顯示了MySQL實際使用的索引的名字。如果它為空(或NULL),則MySQL不使用索引。

      • key_len:
        索引中被使用部分的長度,以位元組計。在本例中,key_len是102,其中firstname佔50位元組,lastname佔50位元組,age佔2位元組。如果MySQL只使用索引中的firstname部分,則key_len將是50。

      • ref:
        它顯示的是列的名字(或單詞“const”),MySQL將根據這些列來選擇行。在本例中,MySQL根據三個常量選擇行。

      • rows:
        MySQL所認為的它在找到正確的結果之前必須掃描的記錄數。顯然,這裡最理想的數字就是1。

      • Extra:
        這裡可能出現許多不同的選項,其中大多數將對查詢產生負面影響。在本例中,MySQL只是提醒我們它將用WHERE子句限制搜尋結果集。

    6. 主鍵索引

      1. 定義

        1. 如果該列的特點是:值唯一,無null值,可以使用primary key 來約束和保證。
        2. 每張表中只能由一個primary key 主鍵索引,如果在不同的列上重複定義primary,報錯:[Err] 1068 - Multiple primary key defined
      2. 解決了什麼問題

        1. 作為索引,提高了查詢效率
        2. 保證了列值唯一,不能有重複值、不能有null值
      3. 如何使用

        1. 檢視索引

          show index from region ;

        2. 建立索引

          create primary key on region (id) ; – 無效

        3. 新增索引

          alter table region add primary key (id) ;-- 3.594s

        4. 刪除索引

          drop primary key on region ;## 無效
          alter table region drop primary key ; – 3.726s

        5. 驗證索引是否生效
          select * from region where id = ‘810305’ ; ## 有索引時:0.001s 無索引時: 0.006s
          explain select * from region where id = ‘810305’ ;

        6. 同一張表中分別定義不同的列為primary key ,

          1. alter table region add primary key (id) ;
          2. alter table region add primary key (Lng) ;
          3. 報錯:[Err] 1068 - Multiple primary key defined
    7. 唯一索引

      1. 定義
        1. 它與前面的"主鍵索引"類似,不同的就是:唯一索引列的值必須唯一,但允許有空值。如果是組合索引,則列值的組合必須唯一
      2. 為什麼使用唯一索引
        1. 提高查詢效率
        2. 保證列值的唯一性,可以有null值
        3. 參考別人的解釋:你為了做到資料不能有重複值,但是資料庫怎麼保證沒有重複值呢?當然是在儲存資料的時候查一遍,那麼怎樣查詢快呢? 當然是建立索引
      3. 如何使用唯一索引
        1. 唯一索引
          show index from region ;
        2. 建立唯一索引
          create unique index np_u_index on region (name,pid);
        3. 新增索引 (可以根據多列值建立唯一索引)
          alter table region add unique index np_u_index (name,pid) ;
        4. 檢視索引
          show index from region ;
        5. 刪除索引
          alter table region drop index np_u_index ;
          drop index np_u_index on region ;
        6. 驗證索引是否生效
          select * from region where name = ‘大堂區’ and pid = ‘820100’ ; ## 有索引時:0.002s 無索引時: 0.005s
          explain select * from region where name = ‘大堂區’ and pid = ‘820100’ ;
    8. 普通索引

      1. 定義
        1. 沒有約束,可以用於任何列,允許null值,允許重複值
      2. 解決了什麼問題
        1. 提高列值作為查詢條件時的查詢效率
      3. 如何使用
        1. 建立索引
          create index name_index on region(name) ;
        2. 檢視索引
          show index from region ;
        3. 新增索引
          alter table region add index name_index (name) ;
        4. 刪除索引
          drop index name_index on region
          alter table region drop index name_index ;
          select * from region where name = ‘大堂區’ ; ## 有索引時:0.001s 無索引時: 0.005s
          explain select * from region where name = ‘大堂區’ ;
    9. 複合索引

      1. 定義

        1. 在多列上建立的普通索引叫做複合索引
        2. 複合索引查詢效率由高到低,從左往右排列,類似於:省市區街道戶
        3. 遵循最左原則,
        4. 複合索引所在的列不能有null值,如果某列中有null值,該列索引無效
        5. 例如索引是key index (a,b,c). 可以支援a | a,b| a,b,c 3種組合進行查詢,但不支援 b,c進行查詢 .當最左側欄位是常量引用時,索引就十分有效。
      2. 解決了什麼問題

        1. 複合索引在資料庫操作間佔用的開銷更小,可以代替多個單一索引
        2. 有兩個概念:窄索引和款索引,窄索引:指索引列為1-2列的索引
        3. 寬索引:指索引列超過2列的索引
        4. 設計索引的一個重要原則:儘量使用窄索引不用寬索引,因為窄索引更加高效
      3. 如何使用

        1. 建立索引
          create index name_pid_yzcode on region (name,pid,yzcode) ;

        2. 檢視索引
          show index from region ;

        3. 新增索引
          alter table region add index name_pid_yzcode (name,pid,yzcode) ;

        4. 刪除索引
          drop index name_pid_yzcode on region ;
          alter table region drop index name_pid_yzcode ;

        5. explain  select * from region  where name = '元氏縣'  ;	
          explain  select * from region  where pid = '130100'  ;  -- 沒有用到索引
          explain  select * from region  where yzcode = '051130'  ;-- 沒有用到索引
          explain  select * from region  where name = '元氏縣' and pid = '130100'  ;
          explain  select * from region  where name = '元氏縣' and pid = '130100' and yzcode = '051130' ;
          explain  select * from region  where  pid = '130100' and yzcode = '051130';-- 沒有用到索引
          
    10. 全文索引

      1. 定義

        1. fulltext型別的索引
        2. 自然語言的全文索引
          1. 常見單詞不會被搜尋,如果某個詞的初夏頻率超過50%
        3. 布林全文索引
      2. 解決了什麼問題

        1. 相比於使用模糊查詢提高了效率。
      3. 如何使用

        1. 建立索引

          1. create FULLTEXT index full_index on region (name) ;
        2. 檢視索引

          1. show keys from region ;
        3. 新增索引

          1. alter table region add FULLTEXT index full_index (name) ;
        4. 刪除索引

          1. drop index full_index on region ;
          2. alter table region drop index full_index ;
        5. 查詢使用索引

        6. 查詢格式:MATCH (columnName) AGAINST (‘string’);

        7. 查詢多列複合全文索引:

          SELECT * FROM student WHERE MATCH(name,address) AGAINST(‘聰 廣東’)

        8. 使用命令:

          • SHOW VARIABLES LIKE ‘ft%’; #ft就是FullText的簡寫 檢視所有的限制引數

            • ft_boolean_syntax + -><()~*:""&| #改變IN BOOLEAN MODE的查詢字元,不用重新啟動MySQL也不用重建索引
              min_word_len 4 #最短的索引字串,預設值為4,(通常改為1)修改後必須重建索引檔案
          • 重新建立索引命令:repair table tablename quick

          • ft_max_word_len 84 #最長的索引字串,預設值為84,修改後必須重建索引檔案

          • ft_query_expansion_limit 20 #查詢括展時取最相關的幾個值用作二次查詢

          • ft_stopword_file (built-in) #全文索引的過濾詞檔案,具體可以參考:

        9. 自然語言 全文索引
          select * from region where match (name) against(‘東城’);

        10. 布林全文索引
          select * from region where MATCH(name) AGAINST('橋西’IN BOOLEAN MODE) ;

    11. 索引的缺點

      1. 佔用磁碟空間

        ​ 首先,索引要佔用磁碟空間。通常情況下,這個問題不是很突出。但是,如果你建立每一種可能列組合的索引,索引檔案體積的增長速度將遠遠超過資料檔案。如果你有一個很大的表,索引檔案的大小可能達到作業系統允許的最大檔案限制。

      2. 增加增刪改時間

        對於需要寫入資料的操作,比如DELETE、UPDATE以及INSERT操作,索引會降低它們的速度。這是因為MySQL不僅要把改動資料寫入資料檔案,而且它還要把這些改動寫入索引檔案。

    12. 索引失效情況

      1. 在索引列上使用: is null 如果列值可以為null索引有效,如果列值不能為null,索引失效; is not null 索引失效;

        1. create index name_index on  region (name) ;                
          show keys from region ;
          update region set name = null where id = '900002' ;
          explain select * from region where name is null ; ## 索引生效  name 可以為 null 
          explain select * from region where name is not null ; ## 索引失效  
          drop index name_index on region ;
          show keys from student ;
          create unique index  name_index on student (name) ;  ## 修改 name屬性不能為null
          explain select * from student where name is null ; ## 索引失效 name 不能為 null 
          explain select * from student where name is not null ; ## 索引失效  
          explain select * from student where id is null ; ## 索引失效  primary key id 
          
      2. or關鍵字, 網上說的情況是:其中一個條件列上面沒有索引,沒有索引怎麼會生效,真是無語!

        1. ## name 有索引,pid沒有索引
          explain select * from region where name = '沙田區' or  pid = '110000' ;## 索引不生效
          explain select * from region where   pid = '110000' or name = '沙田區'  ;## 索引不生效
          explain select * from region where name =  '大堂區' or name  = '氹仔島' ; ## 索引生效
          
      3. 複合索引沒有遵循最左匹配原則時,查詢條件中如果沒有最左的那列,索引不生效

        1. create index name_pid_yzcode on region (name,pid,yzcode) ;
          explain select * from region where pid = '110000' and yzcode = '100000' ; ## 索引不生效
          
      4. 使用like ‘%str%’ ‘%str’ ,索引不生效

        1. explain select * from region where name like '沙田%' ;  ## 索引生效
          explain select * from region where name like '%沙田區%' ;## 索引不生效
          explain select * from region where name like '%田區' ;## 索引不生效
          
      5. 普通索引上使用邏輯運算子: != 索引無效,

        1. explain select * from region where id != 900001 ; ## primary key 索引有效
          create index level_index on region (level) ;
          show index from region ;
          explain select * from region where level != 1 ; ## 索引失效  普通索引
          
      6. 使用比較運算子:±*/ ,還有函式運算 ,沒有在索引列上直接指定結果,索引失效

        1. explain select * from region where level+1 = 2 ; ## 索引失效
          explain select * from region where level-1 = 1 ; ## 索引失效
          explain select * from region where level*1 = 2 ; ## 索引失效
          explain select * from region where level/1 = 3 ; ## 索引失效
          explain select * from region where level =  ( select max(level) from region ) ; ## 索引失效  這個好像不太合適!!嘻嘻
          
      7. show status like ‘Handler_read%’;

    13. 聚簇索引和非聚簇索引

      ​ 更新中····(哈哈哈)