成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

「MySQL系列」索引設計原則、索引失效場景、Limit 、Order By、Group By 等常見場景優化

數據庫 MySQL
MySQL在存儲數據之外,數據庫系統還維護者滿足特定查找算法的 數據結構,這些數據結構以某種方式引用(指向)數據, 這樣就 可以在這些數據結構上實現高級查找算法,這種數據結構就是索引。

 一 索引使用

1.1 概述

1. 定義

索引幫助MySQL高效獲取數據的數據結構(按照一定規則)。

2. 定義解釋

MySQL在存儲數據之外,數據庫系統還維護者滿足特定查找算法的 數據結構,這些數據結構以某種方式引用(指向)數據, 這樣就 可以在這些數據結構上實現高級查找算法,這種數據結構就是索引。

3. 優缺點

優點 提高數據檢索效率,降低數據庫IO成本。通過索引對數據進行排序降低數據排序成本,降低CPU消耗。缺點 實際上索引也是一張表,該表中保存了主鍵與索引字段,并指向實體類的記錄,所以索引列也是要占用空間的。更新表時,MySQL 不僅要保存數據,還要保存一下索引文件每次更新添加了索引列的字段,都會調整因為更新所帶來的鍵值變化后的索引信息。

1.2 索引結構(InnoDB)

MySQL數據庫中默認的存儲引擎InnoDB的索引結構為B+樹,而根據 葉子節點的內存存儲不同,索引類型分為主鍵索引和非主鍵索引。

1. 主鍵索引(聚簇索引)

主鍵索引的葉子節點存儲的是整行數據,其結構如下:


2. 非主鍵索引(二級索引或輔助索引)

而非主鍵索引的葉子節點內容存儲時的主鍵的值,其結構如下: 

1.3 索引使用規則

沒有建立索引,執行計劃如下


建立索引

  1. create index idx_seller_name_status_address on tb_seller(name, status, seller); 

1. 全值匹配,對索引所有列都制定具體值

  1. explain select * from tb_seller where name='小米科技' and status='1' and 
  2. address='北京市'

 

2. 最左前綴法制


違背最左法則,索引失效


如果符合最左法則,但是出現跳躍某一列,只有最左列索引生效:


3. 范圍查詢右邊的列,不能使用索引


根據前面的兩個字段name,status查詢是走索引的,但是最后一 個條件address 沒有用到索引。

4. 索引列上進行運算操作,索引失效


5. 字符串不加單引號,造成索引失效


由于,在查詢是,沒有對字符串加單引號,MySQL的查詢優化器, 會自動的進行類型轉換,造成索引失效。

6. 用or分割開的條件

示例,name字段是索引列 , 而createtime不是索引列,中間是 or進行連接是不走索引的 :

  1. explain select * from tb_seller where name='黑馬程序員' or createtime = '2088-01-01 12:00:00'\G; 

 

7. 以%開頭的Like模糊查詢,索引失效。


解決方案


8. 如果MySQL評估使用索引比全表更慢,則不使用索引


9. is NULL,is NOT NULL有時索引失效。


10. in,not in有時索引失效


11. 盡量使用覆蓋索引,避免select

盡量使用覆蓋索引(只訪問索引的查詢(索引列完全包含查詢列)),減少select。


如果查詢列,超出索引列,也會降低性能。

  1. using index :使用覆蓋索引的時候就會出現 
  2. using where:在查找使用索引的情況下,需要回表去查詢所需的數據 
  3. using index condition:查找使用了索引,但是需要回表查詢數據 
  4. using index ; using where:查找使用了索引,但是需要的數據都在索引列中能找到,所以不需要 
  5. 回表查詢數據 

1.4 索引設計原則

索引的設計可以遵循一些已有的原則,創建索引的時候請盡量考 慮符合這些原則,便于提升索引的使用效率,更高效的使用索引。

  1. 對查詢頻次較高,且數據量比較大的表建立索引。 
  2.  
  3. 索引字段的選擇,最佳候選列應當從where子句的條件中提取,如 
  4. where子句中的組合比較多,那么應當挑選最常用、過濾效果最 
  5. 好的列的組合。 
  6.  
  7. 使用唯一索引,區分度越高,使用索引的效率越高。 
  8.  
  9. 索引可以有效的提升查詢數據的效率,但索引數量不是多多益 
  10. 善,索引越多,維護索引的代價自然也就水漲船高。對于插入、 
  11. 更新、刪除等DML操作比較頻繁的表來說,索引過多,會引入相當 
  12. 高的維護代價,降低DML操作的效率,增加相應操作的時間消耗。 
  13. 另外索引過多的話,MySQL也會犯選擇困難病,雖然最終仍然會找 
  14. 到一個可用的索引,但無疑提高了選擇的代價。 
  15.  
  16. 使用短索引,索引創建之后也是使用硬盤來存儲的,因此提升索 
  17. 引訪問的I/O效率,也可以提升總體的訪問效率。假如構成索引的 
  18. 字段總長度比較短,那么在給定大小的存儲塊內可以存儲更多的 
  19. 索引值,相應的可以有效的提升MySQL訪問索引的I/O效率。 
  20.  
  21. 利用最左前綴,N個列組合而成的組合索引,那么相當于是創建了 
  22. N個索引,如果查詢時where子句中使用了組成該索引的前幾個字 
  23. 段,那么這條查詢SQL可以利用組合索引來提升查詢效率。 

二 常見SQL優化

2.1 數據庫準備

1. sql

  1. CREATE TABLE `emp` ( 
  2.   `id` int(11) NOT NULL AUTO_INCREMENT, 
  3.   `namevarchar(100) NOT NULL
  4.   `age` int(3) NOT NULL
  5.   `salary` int(11) DEFAULT NULL
  6.   PRIMARY KEY (`id`) 
  7. ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; 
  8. insert into `emp` (`id`, `name`, `age`, `salary`) values('1','Tom','25','2300'); 
  9. insert into `emp` (`id`, `name`, `age`, `salary`) 
  10. values('2','Jerry','30','3500'); 
  11. insert into `emp` (`id`, `name`, `age`, `salary`) 
  12. values('3','Luci','25','2800'); 
  13. insert into `emp` (`id`, `name`, `age`, `salary`) values('4','Jay','36','3500'); 
  14. insert into `emp` (`id`, `name`, `age`, `salary`) 
  15. values('5','Tom2','21','2200'); 
  16. insert into `emp` (`id`, `name`, `age`, `salary`) 
  17. values('6','Jerry2','31','3300'); 
  18. insert into `emp` (`id`, `name`, `age`, `salary`) 
  19. values('7','Luci2','26','2700'); 
  20. insert into `emp` (`id`, `name`, `age`, `salary`) 
  21. values('8','Jay2','33','3500'); 
  22. insert into `emp` (`id`, `name`, `age`, `salary`) 
  23. values('9','Tom3','23','2400'); 
  24. insert into `emp` (`id`, `name`, `age`, `salary`) 
  25. values('10','Jerry3','32','3100'); 
  26. insert into `emp` (`id`, `name`, `age`, `salary`) 
  27. values('11','Luci3','26','2900'); 
  28. insert into `emp` (`id`, `name`, `age`, `salary`) 
  29. values('12','Jay3','37','4500'); 
  30. create index idx_emp_age_salary on emp(age,salary); 

2.2 order by優化

1. filesort 排序

第一種是通過對返回數據進行排序,也就是通常說的 filesort排 序,所有不是通過索引直接返回排序結果的排序都叫 FileSort排 序。


2. using index

第二種通過有序索引順序掃描直接返回有序數據,這種情況即為 using index,不需要額外排序,操作效率高。


多字段排序

了解了MySQL的排序方式,優化目標就清晰了:盡量減少額外的排 序,通過索引直接返回有序數據。where 條件和Order by 使用 相同的索引,并且Order By 的順序和索引順序相同, 并且 Order by 的字段都是升序,或者都是降序。否則肯定需要額外的 操作,這樣就會出現FileSort。

3. 對上面兩種進行優化

通過創建合適的索引,能夠減少 Filesort 的出現,但是在某些 情況下,條件限制不能讓Filesort消失,那就需要加快Filesort 的排序操作。對于Filesort , MySQL 現在采用的是一次掃描算 法:一次性取出滿足條件的所有字段,然后在排序區 sortbuffer 中排序后直接輸出結果集。排序時內存開銷較大,但是排序效率 比兩次掃描算法要高。

MySQL 通過比較系統變量 max_length_for_sort_data 的大小 和Query語句取出的字段總大小, 來判定是否那種排序算法,如 果max_length_for_sort_data 更大,那么使用第二種優化之后 的算法;否則使用第一種。

可以適當提高 sort_buffer_size max_length_for_sort_data 系統變量,來增大排序區的大小,提高排序的效率。

2.3 group by優化

由于GROUP BY 實際上也同樣會進行排序操作,而且與ORDER BY 相比,GROUP BY 主要只是多了排序之后的分組操作。當然,如果 在分組的時候還使用了其他的一些聚合函數,那么還需要一些聚 合函數的計算。所以,在GROUP BY 的實現過程中,與 ORDER BY 一樣也可以利用到索引。

如果查詢包含 group by 但是用戶想要避免排序結果的消耗, 則 可以執行order by null 禁止排序。如下 :

  1. drop index idx_emp_age_salary on emp; 
  2. explain select age,count(*) from emp group by age; 

 

優化后

  1. explain select age,count(*) from emp group by age order by null

 

從上面的例子可以看出,第一個SQL語句需要進行"filesort",而 第二個SQL由于order by null 不需要進行 "filesort", 而上 文提過Filesort往往非常耗費時間。

創建索引

  1. create index idx_emp_age_salary on emp(age,salary); 

 

2.4 limit優化

一般分頁查詢時,通過創建覆蓋索引能夠比較好地提高性能。一 個常見又非常頭疼的問題就是 limit5000000,10 ,此時需要 MySQL排序前5000010 記錄,僅僅返回5000000 - 5000010 的記 錄,其他記錄丟棄,查詢排序的代價非常大 。

limit分頁操作, 越往后, 性能越低 :


優化方案

  1. select * from tb_sku t , (select id from tb_sku order by id limit 9000000,1) a where t.id = a.id; 

 

2.5 count優化

在很多的業務系統中,都需要考慮進行分頁操作,但是當我們執 行分頁操作時,都需要進行一次count操作,求取總記錄數,如果 數據庫表的數據量大,在InnoDB引擎中,執行count操作的性能是 比較低的,需要遍歷全表數據,對計數進行累加。

優化方案

  1. ①. 在大數據量的查詢中,只查詢數據,而不展示總記錄數 ; 
  2. ②. 通過緩存redis維護一個表的計數,來記錄數據庫表的總記錄數,在執行插入/刪除時,需要動態更新; 
  3. ③. 在數據庫表中定義一個大數據量的計數表,在執行插入/刪除時,需要動態更新。 

2.6 大批量插入優化

1. 環境準備

  1. CREATE TABLE `tb_user` ( 
  2.   `id` INT(11) NOT NULL AUTO_INCREMENT, 
  3.   `username` VARCHAR(50) NOT NULL
  4.   `passwordVARCHAR(50) NOT NULL
  5.   `nameVARCHAR(20) NOT NULL
  6.   `birthday` DATE DEFAULT NULL
  7.   `sex` CHAR(1) DEFAULT NULL
  8.   PRIMARY KEY (`id`), 
  9.   UNIQUE KEY `unique_user_username` (`username`) 
  10. ) ENGINE=INNODB DEFAULT CHARSET=utf8 ; 

當使用 load 命令導入數據的時候,適當的設置可以提高導入的效率。

對于InnoDB 類型的表,有以下幾種方式可以提高導入的效率:

主鍵順序插入

因為InnoDB類型的表是按照主鍵的順序保存的,所以將導入的數 據按照主鍵的順序排列,可以有效的提高導入數據的效率。如果 InnoDB表沒有主鍵,那么系統會自動默認創建一個內部列作為主 鍵,所以如果可以給表創建一個主鍵,將可以利用這點,來提高 導入數據的效率。

  1. 腳本文件介紹 : 
  2.   sql1.log ----> 主鍵有序 
  3.   sql2.log ----> 主鍵無序 

插入ID順序排列數據:

  1. load data local infile '/root/sql1.log' into table `tb_user` fields terminated by ',' lines terminated by '\n'

 

 插入ID無序排列數據:

關閉唯一性校驗

在導入數據前執行 SET UNIQUE_CHECKS=0,關閉唯一性校驗,在 導入結束后執行 SET UNIQUE_CHECKS=1,恢復唯一性校驗,可以 提高導入的效率。


手動提交事務

如果應用使用自動提交的方式,建議在導入前執行 SET AUTOCOMMIT=0,關閉自動提交,導入結束后再執行 SET AUTOCOMMIT=1,打開自動提交,也可以提高導入的效率。


 

責任編輯:姜華 來源: 花花與Java
相關推薦

2024-05-08 08:18:05

索引失效場景

2022-05-26 08:23:05

MySQL索引數據庫

2024-04-19 13:57:30

索引數據庫查詢

2024-01-05 14:20:55

MySQL索引優化器

2020-10-19 19:45:58

MySQL數據庫優化

2020-07-16 21:20:08

數據庫MySQL死鎖

2020-12-08 09:45:07

MySQL數據庫索引

2022-02-28 08:55:31

數據庫MySQL索引

2022-01-09 18:32:03

MySQL SQL 語句數據庫

2021-10-12 08:43:19

Cobar分庫場景

2024-12-11 08:09:54

2015-05-20 13:48:26

MySQL索引

2023-05-23 22:19:04

索引MySQL優化

2019-08-16 01:58:01

MySQL索引事務

2025-05-28 00:00:01

MySQL場景索引

2024-10-09 23:32:50

2021-05-10 11:15:28

面試索引MySQL

2019-12-18 08:00:09

MySQL數據庫ORDER BY

2022-04-26 08:51:29

MySQLgroup by

2010-10-27 13:47:50

Oracle索引
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 理论片87福利理论电影 | 日韩欧美精品 | 久久久久亚洲 | 国产欧美久久精品 | 欧美a在线 | 拍真实国产伦偷精品 | 成人av电影天堂 | 精品国产区 | 亚洲一区久久 | 亚洲日日 | 97视频在线免费 | a黄视频 | 亚洲午夜av | 99久久精品免费看国产免费软件 | 免费在线观看一区二区 | 亚洲精品一二三 | 桃花av在线| 国产精品日本一区二区不卡视频 | 国产一区二区三区久久久久久久久 | 国产精品欧美日韩 | 国产精品视频网 | 欧美精品在欧美一区二区少妇 | 国产精品91久久久久久 | 91综合在线观看 | 97精品超碰一区二区三区 | 欧美日韩一区二区三区四区五区 | 中文字幕欧美一区 | 欧美高清性xxxxhdvideosex | 成年免费大片黄在线观看岛国 | 午夜精品 | 欧美日韩在线免费观看 | 狠狠干av | 毛片a | 亚洲一区 中文字幕 | 久草在线 | 日韩免费看片 | 亚洲字幕在线观看 | 国产精品99久久久久久动医院 | 99精品国产一区二区三区 | 欧州一区| 在线免费观看黄a |