# 索引設計的原則
1)適合索引的列是出現在where子句中的列,或者連接子句中指定的列;
2)基數較小的類,索引效果較差,沒有必要在此列建立索引;
3)使用短索引,如果對長字符串列進行索引,應該指定一個前綴長度,這樣能夠節省大量索引空間;
4)不要過度索引。索引需要額外的磁盤空間,并降低寫操作的性能。在修改表內容的時候,索引會進行更新甚至重構,索引列越多,這個時間就會越長。所以只保持需要的索引有利于查詢即可。
# 索引設計的原則索引優化規則:
1)如果MySQL估計使用索引比全表掃描還慢,則不會使用索引。
返回數據的比例是重要的指標,比例越低越容易命中索引。記住這個范圍值——30%,后面所講的內容都是建立在返回數據的比例在30%以內的基礎上。
2)前導模糊查詢不能命中索引。
前導模糊查詢不能命中索引:
EXPLAIN SELECT * FROM user WHERE name LIKE '%s%';

非前導模糊查詢則可以使用索引,可優化為使用非前導模糊查詢:
EXPLAIN SELECT * FROM user WHERE name LIKE 's%';

3)數據類型出現隱式轉換的時候不會命中索引,特別是當列類型是字符串,一定要將字符常量值用引號引起來。
EXPLAIN SELECT * FROM user WHERE name=1;

EXPLAIN SELECT * FROM user WHERE name='1';

4)復合索引的情況下,查詢條件不包含索引列最左邊部分(不滿足最左原則),不會命中符合索引。
name,age,status列創建復合索引:
ALTER TABLE user ADD INDEX index_name (name,age,status);

根據最左原則,可以命中復合索引index_name
EXPLAIN SELECT * FROM user WHERE name='swj' AND status=1;

**注意:**
最左原則并不是說是查詢條件的順序。
EXPLAIN SELECT * FROM user WHERE name='swj' AND status=1;

**注意:**
而是查詢條件中是否包含索引最左列字段:
EXPLAIN SELECT * FROM user WHERE status=2 ;

5)union、in、or都能夠命中索引,建議使用in。
**注意:**
查詢的CPU消耗:or>in>union。
6)用or分割開的條件,如果or前的條件中列有索引,而后面的列中沒有索引,那么涉及到的索引都不會被用到。
EXPLAIN SELECT * FROM payment WHERE customer_id = 203 OR amount = 3.96;

7)負向條件查詢不能使用索引,可以優化為in查詢。
負向條件有:!=、<>、not in、not exists、not like等。
負向條件不能命中索引:
EXPLAIN SELECT * FROM user WHERE status !=1 AND status != 2;

可以優化為in查詢,但是前提是區分度要高,返回數據的比例在30%以內:
EXPLAIN SELECT * FROM user WHERE status IN (0,3,4);

8)范圍條件查詢可以命中索引。范圍條件有:、>=、between等。
范圍條件查詢可以命中索引:
EXPLAIN SELECT * FROM user WHERE status>5;

**注意:**
范圍列可以用到索引(聯合索引必須是最左前綴),但是范圍列后面的列無法用到索引,索引最多用于一個范圍列,如果查詢條件中有兩個范圍列則無法全用到索引:
EXPLAIN SELECT * FROM user WHERE status>5 AND age<24;

**注意:**
如果是范圍查詢和等值查詢同時存在,優先匹配等值查詢列的索引:
EXPLAIN SELECT * FROM user WHERE status>5 AND age=24;

8)數據庫執行計算不會命中索引。
EXPLAIN SELECT * FROM user WHERE age>24;

EXPLAIN SELECT * FROM user WHERE age+1>24;

計算邏輯應該盡量放到業務層處理,節省數據庫的CPU的同時最大限度的命中索引。
9)利用覆蓋索引進行查詢,避免回表。
被查詢的列,數據能從索引中取得,而不用通過行定位符row-locator再到row上獲取,即“被查詢列要被所建的索引覆蓋”,這能夠加速查詢速度。
EXPLAIN SELECT status FROM user where status=1;

**注意:**
當查詢其他列時,就需要回表查詢,這也是為什么要避免SELECT*的原因之一:
EXPLAIN SELECT * FROM user where status=1;

10)建立索引的列,不允許為null。
單列索引不存null值,復合索引不存全為null的值,如果列允許為null,可能會得到“不符合預期”的結果集,所以,請使用not null約束以及默認值。
# 索引總結:
a. 更新十分頻繁的字段上不宜建立索引:因為更新操作會變更B+樹,重建索引。這個過程是十分消耗數據庫性能的。
b. 區分度不大的字段上不宜建立索引:類似于性別這種區分度不大的字段,建立索引的意義不大。因為不能有效過濾數據,性能和全表掃描相當。另外返回數據的比例在30%以外的情況下,優化器不會選擇使用索引。
c. 業務上具有唯一特性的字段,即使是多個字段的組合,也必須建成唯一索引。雖然唯一索引會影響insert速度,但是對于查詢的速度提升是非常明顯的。另外,即使在應用層做了非常完善的校驗控制,只要沒有唯一索引,在并發的情況下,依然有臟數據產生。
d. 多表關聯時,要保證關聯字段上一定有索引。
e. 創建索引時避免以下錯誤觀念:索引越多越好,認為一個查詢就需要建一個索引;寧缺勿濫,認為索引會消耗空間、嚴重拖慢更新和新增速度;抵制唯一索引,認為業務的唯一性一律需要在應用層通過“先查后插”方式解決;過早優化,在不了解系統的情況下就開始優化。
- 開發語言
- java
- Java基礎篇
- Java多線程篇
- 進程和線程的區別,進程間如何通信
- 什么是線程上下文切換
- 什么是死鎖
- 死鎖的必要條件
- Synchrpnized和lock的區別
- 什么是AQS鎖
- 為什么AQS使用的雙向鏈表
- 有哪些常見的AQS鎖
- sleep()和wait()的區別
- yield()和join()區別
- Java線程池
- SpringBoot
- spring boot 項目開發常用目錄結構
- Mybatis-Plus
- MyBatisPlus的CRUD操作
- Mybatis-Plus主鍵ID生成策略
- JVM
- JVM組成
- 字節碼文件的組成
- 類的生命周期
- JVM、JRE和JDK
- arthas
- 使用阿里arthas不停機解決線上問題
- Java IO
- php
- 安裝swoole
- composer部分
- windows安裝composer
- composer PSR-4映射
- composer 鏡像同一個版本替換
- composer官方鏡像庫
- swoole部分
- swoole安裝
- thrift部分
- linux下安裝thrift
- PHP使用Thrift
- lnmp部分
- 架構的工作原理
- tp5框架生命周期
- zookeeper部分
- zookeeper安裝
- sort
- TCP和UDP的區別
- 軟件
- xdebug
- vscode+phpstudy+xdebug無法斷點(踩坑記)
- Hyperf框架
- 注解
- 通過注解定義路由
- go
- 開發方案
- 抖音
- 抖音達人視頻發布與統計
- 安全問題
- 微信
- 微信公眾平臺怎樣實現用戶點擊鏈接向公眾號發消息
- CDN加速OSS計費說明
- 程序設計
- 正則表達式
- 面向對象
- 設計模式
- 創建型模式
- 工廠模式
- 單例模式
- 結構型模式
- 適配器模式
- 行為型模式
- 策略模式
- 觀察者模式
- 算法部分
- 位運算
- 排序算法
- 雙指針
- 貪心算法
- 動態規劃
- 二分查找
- 華為題庫
- 技術棧
- mq
- MQ 的優勢和劣勢
- rabbitmq部分
- windows安裝rabbitmq
- RabbitMQ 簡介
- 工作模式
- 高級特性-消息可靠投遞-confirm
- 高級特性-消息可靠投遞-return
- 高級特性-Consumer Ack
- 高級特性-消費端限流
- 高級特性-TTL
- 高級特性-死信隊列
- Centos7下安裝rabbitmq
- 數據庫
- MongoDB
- MongoDB 相關概念
- Mysql
- 索引總結
- MySQL架構圖
- InnoDB和MyISAM的區別
- 索引設計與優化
- 悲觀鎖和樂觀鎖
- mysql如何解除死鎖狀態
- 查詢慢
- 數據庫主鍵的優缺點
- MySQL鎖詳解
- SQL語句分類
- 開查詢賬號
- 數據庫遷移
- MySQL實戰知識點
- mysql清理binlog日志
- 面試總結
- 事務隔離
- 聚集索引與非聚集索引
- B樹和B+樹
- docker
- docker-desktop安裝的坑點
- docker在linux平臺下安裝
- Ubuntu安裝Docker
- 常用命令
- 適用于 Linux 的 Windows 子系統沒有已安裝的分發版
- docker核心架構圖
- docker安裝lnmp環境
- docker安裝redis
- dockerfile
- docker-compose
- 清除容器日志
- linux
- Ubuntu 更換國內源
- centos
- 常用命令
- virtualbox
- 關于VirtualBox安裝Ubuntu時界面顯示不全,沒有下一步選項
- linux復制當前目錄到其子目錄下
- 命令
- cat和>、>>
- crontab命令
- 空間大小查詢命令
- shell登錄和非shell登錄
- nginx
- 正向代理
- 反向代理
- 負載均衡
- 分割Nginx的access.log日志并保留30天一個月時長,自動刪除多余的日志
- linux安裝nginx
- git
- 生成秘鑰
- 常用命令
- Linux中git保存用戶名密碼
- git清除賬號密碼
- 設置git store 存儲賬號密碼
- git submodule 使用小結
- 微服務
- 微服務技術棧
- nacos
- Nacos服務分級存儲模型
- Nacos配置管理-配置熱更新
- Nacos集群搭建
- 微服務保護
- 初識Sentinel
- 隔離和降級
- es
- DSL查詢語法-相關性算法
- DSL查詢語法-FunctionScoreQuery
- DSL查詢語法-BooleanQuery
- 搜索結果處理-排序
- es深度分頁問題
- 自動補全
- elasticsearch 設置密碼
- redis
- redis簡介
- linux安裝redis
- 安裝redis擴展
- redis數據類型
- redis常見問題
- PHP 使用 Redis 實現分布式鎖
- 緩存更新策略
- [ Redis ] AOF 和 RDB 的相關介紹以及相關配置
- 分布式鎖的8大坑
- 分布式鎖-Redisson
- 內存回收
- UV統計
- Redis主從集群
- redis哨兵
- Redis安裝目錄下常見文件
- 通訊原理概述
- windows
- Win系統端口被占用
- Windows10 WSL2限制cpu和內存
- jekins
- 持續集成
- centos卸載gitlab
- jenkins搭配gitlab的webhook實現自動化部署
- 大數據
- Linux集群分發腳本xsync
- hadoop
- hadoop安裝
- hadoop配置文件
- clickhouse
- ClickHouse 安裝部署
- flink
- 數據倉庫
- zookeeper
- zookeeper分布式安裝
- ZK集群啟動停止腳本
- kafka
- kafka分布式安裝
- kafka集群啟動停止腳本
- flume
- flume分布式安裝
- Flume配置
- Flume使用
- maxwell
- Maxwell簡介
- Maxwell部署
- Maxwell使用
- MaxwellBootstrapUtility - Connections could not be acquired from the underlying database
- 線上事故