MySQL數據庫部分面試題,初級菜🦃,後面再補充。
MySQL基礎部分學習:https://blog.csdn.net/JAYU_37/article/details/101800297
文章目錄
- 1. 數據庫基礎知識
- 2. 引擎
- 3. 索引
- 3.1 什麼是索引
- 3.2 索引有哪些優點
- 3.3 索引有哪幾種類型
- 3.4 索引的使用場景(重點)
- 3.5 索引的基本原理
- 3.6 創建索引的原則(!!重要)
- 3.7 索引的設計原則
- 3.8 創建索引的三種方式
- 3.9 創建索引需要注意什麼?
- 3.10 使用索引一定能提高查詢效率嗎?
- 3.11 百萬級數據如何刪除
- 4. 事務
- 5. 鎖
- 6. 視圖
- 7. 存儲過程與函數
- 8. 常用的SQL語句
- 8.1 SQL語句主要分爲哪幾類
- 8.2 超鍵,候選鍵,主鍵,外鍵
- 8.3 SQL約束有幾種?
- 8.5 什麼是子查詢
- 8.6 子查詢的三種情況
- 8.7 MySQL中的in與exists區別?
- 8.8 varchar與char有什麼區別?
- 8.9 varchar(50),其中50的含義?
- 8.10 mysql中int(10),char(10),以及varchar(10)的區別
- 8.11 float和double的區別
- 8.12 drop,delete與truncate的區別?
- 8.13 union與union all的區別?
- 9. SQL優化
1. 數據庫基礎知識
1.1 爲什麼要使用數據庫
如果
數據保存在文件:
優點:數據永久保存
缺點:速度比內存操作慢,頻繁的IO操作,查詢數據不方面
數據保存在內存:
優點:存取速度快
缺點:數據不能永久保存
但是如果
數據保存在數據庫:
1)數據可以永久保存
2)使用SQL語句查詢方面,效率高
3)管理數據方便
1.2 什麼是SQL
結構化(Structured Query Language)查詢語言,簡稱SQL,作用:用於存儲,查詢,更新和管理數據庫系統。
1.3 什麼是MySQL
MySQL是時下最流行的一款關係型數據庫,屬於Oracle旗下產品,在Java企業級中開發非常常用,因爲MySQL是開源的,免費的,易於擴展。
1.4 數據庫的三大範式
第一範式:每個列都是不可分割的數據項。
第二範式:在第一範式的基礎上,消除了非主屬性對主屬性的部分依賴
第三範式:在第二範式上,消除了非主屬性對其它非主屬性的的依賴,即消除了傳遞函數依賴。
2. 引擎
2.1 MyISAM引擎和InnoDB引擎有什麼區別?
- InnoDB是聚簇索引,而MyISAM是非聚簇索引
- InnoDB主鍵索引的葉子節點存儲着行數據,因此主鍵索引非常高效。
- MyISAM是MySQL的默認引擎,不提供事務的支持,也不提供行級鎖和外鍵。
- InnoDB提供了數據庫ACID的支持,還提供行級鎖和外鍵,它的設計目的就是處理大數據容量的數據庫管理系統。
2.2 InnoDB引擎的四大特性
- 插入緩存
- 二次寫
- 自適應hash索引
- 預讀
2.3 存儲引擎的選擇
如果沒有特別的需求,使用默認的InnoDB即可。
MyISAM:以讀寫插入爲主的應用程序,比如博客系統,新聞門戶網站。
InnoDB:更新(更新刪除)頻率高的,或者要保證數據的完整性,併發量高,支持事務和外鍵,如OA管理系統。
3. 索引
3.1 什麼是索引
索引是一種特殊的文件,InnoDB數據表上的索引是數據表空間的一部分,它包含了對數據表中所有記錄的引用指針。
索引是一種數據結構,數據庫索引,是數據庫管理系統中一個排序的數據結構,以協助快速查詢,更新數據庫中表數據,對於一本書而言,索引相當於目錄,索引是一個文件,需要佔據物理空間的。
3.2 索引有哪些優點
優點:
- 通過使用索引,可以大大提高數據的檢索速度,這也是創建索引的最主要原因。
- 通過使用索引,可以在查詢過程中,優化隱藏器,提高查詢性能。
缺點:
- 時間方面:創建索引需要耗費時間,對錶中的數據進行增加,刪除和修改的時候,索引也要動態維護,會減低增/改/刪的性能。
- 空間方面:索引需要佔物理空間。
3.3 索引有哪幾種類型
- 主鍵索引:一般不需要我們創建,數據列不允許重複,不允許爲null,一個表只能有一個主鍵。
- 唯一索引:索引列值必須唯一,可以有null值
- 複合索引:一個索引包含多個列。
- 全文索引:是目前搜索引擎使用的一種關鍵性技術
3.4 索引的使用場景(重點)
-
where:提高效率,如果有多個索引,就會選擇一個最優的索引,指的是區分度最高的。
-
order by:爲order by的排序字段添加索引,可以提升排序的效率。
-
join:對join的on涉及的字段建立索引可以提高效率。
-
索引覆蓋:如果查詢的字段都有建立索引,那麼引擎會直接在索引表中查詢而不會直接訪問原始數據(如果其中有一個字段沒有建立索引),就會進行全表掃描。這就叫所,索引覆蓋。因此,我們需要儘可能的在select後寫有必要查詢的字段,避免使用select * 查詢,以增加索引覆蓋的機率。
但是不要想着爲每個字段創建索引,因爲優先使用索引的優勢在於其體積小。
3.5 索引的基本原理
索引用來快速尋找哪些具體特定值的記錄,如果沒有索引,執行查詢時需要遍歷整張表
索引的原理很簡單,就是將無序的數據變成有序的查詢。
3.6 創建索引的原則(!!重要)
索引雖好,但不可無限制的使用它,最好符合下面的規則:
- 最左前綴匹配原則,這個是組合索引非常重要的原則,mysql會一直從左至右進行匹配查詢,,遇到
> < between like
就停止匹配,如:
a = 1 and b =2 and c>3 and d= 4,如果建立(a,b,c,d)順序的組合組合索引,
d是用不到索引的,如果建立(a,b,c,d)的索引都用得到,則它們可以任意順序.
- 創建索引的字段應選擇頻繁查詢的字段
- 更新頻繁的字段不適合用於創建索引
- 若是不能有效區分數據的列不適合用於索引
- 儘量使用擴展索引,如果表中有索引(a),現在要交(a,b)索引,那麼只需要修改原來的(a)索引即可。
- 定義有外鍵的數據列一定要建立索引。
- 對於定義我text,image和bit的數據類型,不要建立索引。
- 對於哪些查詢中很少設計的列,重複值比較多的列不適合建立索引。
3.7 索引的設計原則
- 儘量使用短索引字段,如果對長的字符串進行索引,應指定一個前綴長度,這樣可以節省大量索引時間。
- 表中的數據如果較少,沒必要使用索引。
- 適合所有的列是出現在where子句中的列,或連接子句指定的列。
- 不要過度使用索引,索引需要額外的磁盤空間,並降低操作的性能,在修改更新表的時候,索引會對更新的進行重構,索引列越多,這個時間就越長,所以索引應更適合用於查詢。
3.8 創建索引的三種方式
-
第一種,在創建表的時候創建
格式:
CREATE TABLE 表名( 屬性名 數據類型[完整性約束條件],
屬性名 數據類型[完整性約束條件],
…
屬性名 數據類型
[ UNIQUE | FULLTEXT | SPATIAL ] INDEX | KEY
[ 別名] ( 屬性名1 [(長度)] [ ASC | DESC] )
);[ UNIQUE | FULLTEXT | SPATIAL ] 可選字段:
UNIQUE :表示唯一
FULLTEXT :全文搜索
SPATIAL :空間索引
INDEX | KEY :二選一即可,都表示創建索引
例子:
CREATE TABLE user_index2 (
id INT auto_increment PRIMARY KEY,
first_name VARCHAR (16),
last_name VARCHAR (16),
id_card VARCHAR (18),
information text,
KEY name (first_name, last_name),
FULLTEXT KEY (information),
UNIQUE KEY (id_card)
);
查詢表中索引:show index from 表名
- 建立表之後,開始建立索引
create index 索引名 on 表名(列名); //創建索引
show index from 表名;
drop index 索引名 on 表名;
- 使用alter table命令增加索引
alter table 表名 add index 索引名(列名);
alter table可以創建普通索引,唯一索引和主鍵索引,索引名如果不寫時,MySQL默認以第一個列名作爲索引名,另外alter table允許在單個語句中修改多個表。
3.9 創建索引需要注意什麼?
非空字段:應指定列爲NOT NULL,除非你想存儲NULL值,在mysql中,含有空值的列很難進行查詢優化,因爲它們使得索引運算更加複雜,可以用0或空串替換空值。
應取值離散大的字段:離散大的字段說明列變量之間的差異程度就越大,查詢到的數據就越精確。
索引的字段越小越好:數據庫存儲數據以頁爲單位,一頁存儲的數據越多,一次IO操作獲取的數據效率越低。
3.10 使用索引一定能提高查詢效率嗎?
通過索引查詢數據比全表掃描要快,但是:
索引需要空間來存儲,也需要時間來維護,每當有記錄在表中增減,索引本身也會被修改,這也是需要消耗性能,所以索引多用於查詢。
3.11 百萬級數據如何刪除
- 先刪除索引(此時大約耗時3分鐘)
- 再刪除數據庫中無用的數據
- 刪除後重新建立索引,此時因爲數據少了,所以創建索引非常快
- 再去刪除就很快了
4. 事務
4.1 什麼是事務
事務是一個不可分割的數據庫操作序列,也是數據庫併發控制的基本單位,其執行結果必須是使數據庫從一種狀態變到另一種狀態。事務時邏輯上的一組操作,要麼全部執行,要麼都不執行。
4.2 事務的四大特性(ACID)
關係型數據庫需要遵循ACID規則
原子性:事務是最小的執行單位,不允許分割,要麼全部執行成功,要麼全部執行不起作用。
一致性:執行事務前後,數據不變,多個事務對同一數據的讀取時相同的,如轉賬業務,無論事務執行成功與否,參與轉賬的兩個賬戶餘額之和應該保持不變。
隔離性:併發訪問數據庫時,一個用戶的事務不被其它事務所幹擾,各個併發事務之間數據庫是獨立的。
持久性:一個事務提交後,它對數據庫中的數據改變是持久的,即使數據庫發生故障也不應該對其有任何的影響。
4.3 什麼是髒讀,幻讀,不可重複讀
髒讀:A事務讀取B事務尚未提交的數據,如果此時B回滾,則A事務讀取的數據就是髒數據。
幻讀:事務A執行,查詢第一次數據總量有100條,事務A還沒結束,此時事務B介入,多添加了100條數據並提交,事務A再次查詢發現數據量變成200條,造成一次事務兩次讀取的數據總量不一致。
不可重複讀:事務A執行,查詢第一次的數數據爲a = 10,事務A還沒結束,此時事務B介入將a改爲a = 20並提交,事務A再次查詢a = 20,造成一次事務內兩次讀取數據不一致。
4.4 什麼是事務的隔離級別,MySQL的默認隔離級別是什麼?
爲達到事務的四大特性,數據庫定義了4種不同的隔離級別,由低到高依次爲
Read Uncommited ---讀未提交
Read Commmited ---讀已提交
Repeatable Read ---可重複讀
Serializable ---可串行化
這四個隔離級別可以逐個解決髒讀,不可重複讀,幻讀這幾類問題。
隔離級別 | 髒讀 | 不可重複讀 | 幻讀 |
---|---|---|---|
Read Uncommited | √ | √ | √ |
Read Commmited | × | √ | √ |
Repeatable Read | × | × | √ |
Serializable | × | × | × |
可見
Read Uncommited:允許讀未提交是最低的隔離級別,可能會造成解決髒讀,不可重複讀,幻讀。
Read Commmited:允許讀併發事務已提交的數據,解決了髒讀問題。
Repeatable Read:可重複讀,對同一字段的多次讀取都是一樣的,可以解決髒讀,不可重複讀,當仍然可能出現幻讀。
Serializable:可串行化,最高的隔離級別,完全服從ACID的隔離級別,所有的事務依次逐個執行,互不干擾,該級別可以解決髒讀,不可重複讀,幻讀。
5. 鎖
5.1 數據庫的樂觀鎖和悲觀鎖是什麼?怎麼實現?
數據庫管理系統的併發控制的任務是確保在多個事務同時存取數據庫中同一數據時不破壞事務的隔離性和統一性以及數據庫的統一性。樂觀併發控制(樂觀鎖)和悲觀併發控制(悲觀鎖)是併發控制採取的主要手段。
樂觀鎖:假設不會發生併發衝突,只是在提交操作時檢查是否違法數據完整性,在修改數據的時候把事務鎖起來,通過version的方式來進行鎖定。實現方式:一般使用版本號機制或CAS算法。
悲觀鎖:假設會發生併發衝突,屏蔽一切可能違反數據完整性的操作,在查詢的時候就把事務鎖起來,直到提交事務。實現方式:使用數據庫的鎖機制。
使用場景:
如果是多寫的情況,一般容易引起衝突,悲觀鎖從一開始就加上鎖,從而保證是事務的安全性,所以悲觀鎖比較適合用於多寫。
如果是多讀,則衝突會很少發生,這樣就省去了鎖的開銷,於是樂觀鎖會更適合。
6. 視圖
6.1 什麼是視圖,爲什麼使用視圖?
視圖:爲了提高複雜SQL語句的複用性和表操作的安全性,MySQL數據庫管理系統引入了視圖,所謂視圖,是一張虛擬表,在物理空間上並不存在,但但內容與真實表相似,包含一系列帶有名稱的行和列。但是,視圖並不在數據庫中以存儲的數值存在,行和列的數據來於自定義視圖的查詢所引用的基本表,並在具體引用視圖時動態生成。
6.2 視圖有哪些特點
- 視圖的列可以來自不同的表,是表的抽象和邏輯意義上建立的新關係。
- 視圖是基本表產生出來的虛表。
- 視圖的建立和刪除不影響基本表。
- 對試圖內容的增刪改直接影響基本表。
- 當視圖來自多個基本表的時候,不允許添加和刪除數據。
6.3 視圖的使用場景
視圖的根本用途:簡化SQL查詢,提高開發效率,兼容老的表結構。
使用場景
- 重用SQL語句
- 簡化複雜的SQL語句,在編寫SQL後,可以方面的重用它而不必知道它的基本查詢細節。
- 使用表的部分,而不是整個表
- 保護數據,可以給用於授權表的部分訪問權限而不是整個表的訪問權限。
- 更改數據格式和表示,視圖可返回與底層表的表示和格式不同的數據。
6.4 視圖的優缺點
優點:
- 查詢簡單化,視圖能簡化用戶得操作。
- 數據安全性。視圖使用戶能夠以多種角度看待同一數據,能夠對機密數據提供安全保護。
- 邏輯數據獨立性。視圖對重構數據庫提供一定程度得邏輯獨立性。
缺點:
- 性能。數據庫必須把視圖的查詢轉成基本表得查詢,如果這個視圖是由一個複雜的多表查詢所定義,那麼即使是一個視圖的簡單查詢,數據庫也把他變成一個複雜的結合體,需要花費一定的時間。
- 修改限制:當用戶試圖修改視圖的某些行時,數據庫需要把它轉換爲對基本表的某些行的修改。對於簡單視圖,可以對其進行插入和刪除數據,但是對複雜的視圖,可能是不可以修改的。
這些視圖有以下特徵:
- 有union集合操作符的視圖
- 有group by子句的視圖
- 有聚合函數的視圖,如AVG/SUM/MAX
- 使用DISTINCT關鍵字的視圖
- 連接表的視圖
6.5 什麼是遊標
遊標是系統爲用戶開設的一個緩衝區,存放SQL語句的執行結果,每個遊標都有一個名字,用戶可以通過遊標逐一獲取記錄並賦值給主變量,交由主語言進一步處理。
7. 存儲過程與函數
8. 常用的SQL語句
8.1 SQL語句主要分爲哪幾類
數據庫定義語言(DDL):增刪改,create drop alter
數據庫查詢語言(DQL): 查詢 select
數據庫操縱語言(DML):操作數據 insert update delete
數據庫控制功能(DCL):權限控制 grant revoke commit rollback
alert和update有什麼區別?
alter是修改表結構的,例如增加,修改和刪除表字段名
update是修改某一行或者某一列的值
8.2 超鍵,候選鍵,主鍵,外鍵
超鍵:在關係中能夠唯一標識元組的屬性集稱爲關係模式的超鍵
候選鍵:最小的超鍵,沒有多餘屬性的超鍵。
主鍵:數據庫表中對存儲數據對象給予唯一和完整性標識的數據列或屬性的組合,一個數據列只能有一個主鍵,而且主鍵不能沒有,不能爲空。
外鍵:在一張表中存在的屬性字段,在另一張表中是主鍵。
8.3 SQL約束有幾種?
有5種:
-
NOT NULL:字段不能爲空
-
UNIQUE:字段內容唯一
-
PRIMARY KEY:主鍵約束,字段在一張表中只允許出現一次
-
FOREIGN KEY:外鍵約束,預防破壞表之間的關係也能防止非法數據插入外鍵列。
left outer join == left join right outer join == right join
-
聯合查詢:union 相同記錄合併,union all不會合並相同的記錄行
-
全連接:MySQL不支持全連接,可以使用外連接
例子:https://blog.csdn.net/weixin_43781127/article/details/89180734
8.5 什麼是子查詢
條件:一條SQL語句的查詢結果作爲另一條SQL語句的查詢條件或查詢結果
嵌套:多條SQL語句嵌套使用,內部的SQL查詢稱爲子查詢。
8.6 子查詢的三種情況
- 查詢是單列的情況,結果集是一個值,父查詢使用
> < =
等運算符:
select * from emp where eid = (select max(salary) from emp);
- 子查詢是單列的情況,結果集類似於一個數組,父查詢使用in
select * from emp where eid in (select * from max(salary) fromemp );
- 子查詢是一個多行多列的情況:結果集類似於一張虛表,不能用於where條件,用於select 子句中作爲子表
1. 查詢2011年後入職的員工信息
2. 查詢所有的部門信息,與上面的虛表中信息的對比,找出所有部門id相同的員工
select * from dept d,(select * from emp where join_data > 2011) e,where e.dept_id = d.id;
3. 使用表連接
select d.* e.* from dept d inner join emp e where d.id = e.dept_id and e,join_data > 2011;
8.7 MySQL中的in與exists區別?
MySQL的in語句是把外表和內表做hash連接,而exists語句是對外表做loop循環,每次loop再對內標進行查詢。
exists的效率並不一定比in高,分如下場景:
- 如果兩張表的大小相當,那麼in和exists的效率相當
- 如果一張表大,一張表小,則子查詢大的用exists,小的用in
- 如果子查詢查詢語句中用到了not in,那麼內外表都進行了全表掃描,並且沒有用到索引。
而not exists查詢內外表都會用到索引,因此效率比not in快
8.8 varchar與char有什麼區別?
varchar:
- varchar是可變長字符串,長度可變的。
- 插入的數據有多大就按照多長來存儲。
- 因爲長度不固定,所以存取比較慢,但是不佔多餘的空間,以時間換空間的做法
- 對於varchar來做,最多能存放65532個字符
char:
- 表示的是長字符串,字符串長度固定
- 如果插入的數據長度 < char的固定長度,空閒位置用空格表示
- 因爲長度固定,唯一存取比較快,但是會佔據多餘的空間
- 對於char來說,最多能存放的字符字數255與編碼無關
總之,結合性能角度,char(更快),varchar(更省空間),所以具體場景具體使用。
8.9 varchar(50),其中50的含義?
50代表的是50個字符。
8.10 mysql中int(10),char(10),以及varchar(10)的區別
- int(10)表示的是顯示數據長度,不是存儲數據的大小,char(10),varchar(10),表示的是存儲10個字符的數據。
int(10):的數據長度爲佔32個字節
char(10):10爲固定長度,不足補空格,最多10個字符。
varchar(10):10個可變長度,不足補空格,最多10個字符。
- char(10)表示存儲定長10個字符,不足10個就用空格補齊,佔用更多的存儲空間。
- varchar(10)表示存儲10個可變長度的字符,存儲幾個就是多少個,空格也算一個,這點和char(10)的空格不一樣的地方
8.11 float和double的區別
float:
float的數據可以最多存儲8位10進制,並且在內存中佔4個字節
double:
float的數據可以最多存儲8位16進制,並且在內存中佔8個字節
8.12 drop,delete與truncate的區別?
三者都表示刪除
delete | truncate | drop | |
---|---|---|---|
類型 | DML | DDL | DDL |
回滾 | 可回滾 | 不可回滾 | 不可回滾 |
刪除內容 | 表結構還在,只是刪除表的一部分行數據 | 表結構還在,刪除表的數據 | 從數據庫中刪除表,連同表的索引和權限一併刪除 |
刪除速度 | 刪除速度慢,需要逐行刪除 | 刪除速度快 | 刪除速度最快 |
8.13 union與union all的區別?
union all :會合並重復的記錄行
union:不會合並重復的記錄行,效率比union all高
9. SQL優化
9.1 MySQL分頁limit
limit用法:
# 查詢6-5條數據行數據,5是起始位置,10是查詢的條數
select * from table limit 5,10
# 查詢一個偏移量到結束所以的記錄行
select * from table limit 5,-1
# 如果只給一個參數表示的是返回最大記錄行
select * from table 5
= select * from table 0,5 # 表示返回前5行
如果遇到從2000000行開始查詢10條數據
explain select *from table limit 2000000,10
這種效率很低,可以使用優化方案:
explain select * from table t,(select * from table order by id limit 2000000,10) a where a.id = .t.id
另外一種方案適用於主鍵自增
explain select * from table where id>2000000 limit 10
9.2 MySQL慢查詢日誌
慢查詢日誌用於爲我們快速定位慢查詢,用於記錄執行時間超過某個臨界值的SQL日誌,爲我們的優化做參考。
# 開啓慢查詢
#配置項
slow_query_log
# 查看是否開啓慢查詢
show variable like 'slow_query_log';
# 開啓慢查詢
set global slow_query_log = on
#設置臨界時間
# 配置項
long_query_time
# 查看臨界時間
show variable like 'long_query_time';
# 設置臨界時間
show variable like 'long_query_time';
實際操作的時候,應該從長時間設置到短時間,將最慢的SQL優化掉。
9.3 MySQL爲什麼要儘量設置一個主鍵
主鍵是保證數據行在數據表中唯一性的保障,設置主鍵後,可以提高對後續的增刪改查的效率和範圍的安全性。
9.4 主鍵使用自增ID還是UUID
使用主鍵自增,不要使用UUID。
因爲在InnoDB存儲引擎中,主鍵是以聚簇索引存在的,在數據量大的情況下,使用主鍵id的性能要優於使用UUID。
關於主鍵是聚簇索引,如果沒有主鍵InnoDB會選擇一個唯一鍵作爲主鍵使用,如果沒有唯一鍵,會生成一個隱式的主鍵。
9.5 爲什麼字段要求定義約束爲not null
null 會佔用更多的字符,而且有可能出現很多預期不符的情況。
9.6 如果要存儲密碼散列,應該使用什麼字段進行存儲?
密碼散列,鹽,用戶身份證等固定長度的應該使用char來存儲,可以節省空間和提高檢索效率。
9.7 優化子查詢
explaint select * from t_user where id in (select user_id from user_role);
使用join優化
explaint select * from t_user u, user_role r where u.id = r.user_id;
連接join效率更高一點,因爲MySQL不需要在內存中創建臨時表來完成這個需要兩個步驟的查詢步驟。
9.8 優化關聯查詢
- 確定on或者using子句是否有索引。
- 確保group by 或 order by只有一個表中的列,這樣MySQL才能使用索引。
9.9 優化union查詢
union all的效率高於union
9.10 優化where子句
對於此類問題,首先應該定位低效SQL,然後根據SQL語句可能低效的原因做排查,先從索引入手,如果索引沒問題考慮一下幾方面:
SQL優化的一下方法:
- 對查詢進行優化,儘量避免使用全表掃描,首先考慮在where 或者oder by後面字段建立索引。
- 應儘量避免在where子句中的字段進行null值得判斷,這樣將使引擎放棄索引而進行全表掃描:
select * from t where num is null
# 可以在創建表得時候爲字段添加默認值 0 表示空,查詢得時候可以‘
select * from t where num = 0;
- 應儘量避免在where子句得列中使用
!= > <
等操作符進行運算,否則引擎會泛起索引而進行全表掃描,在字段類型爲varchar的時候,如果要傳1,不要直接寫1,而是要寫'1'
,否則,mysql底層會將字段進行運算,導致所有失效。 - 應避免在where條件使用or來連接條件,很容易造成引擎放棄所有來進行全表掃描,應使用union替換來優化,參考
9.11
- in 和 not in也要慎用,否則也可能造成索引失效
not in會使索引失效,也儘量避免使用in,可以使用between替換
select * from t where num in(1,2,3);
-- 使用between替換
select * from t where num = 1 and 3;
- 下面的查詢也將導致全表掃描
select * from t where name like "%李"
若要提高效率,可以考慮全文檢索。
7. 如果在where子句中使用參數,也會導致全表掃描。因爲SQL在運行使纔會解析全局變量,但優化程序不能將訪問計劃推遲到運行時,所以它必須在編譯時選擇,,然而如果在編譯時建立訪問計劃,變量的值還是未知的,因此無法作爲索引的選擇輸入項:
select id from t where num = @num;
# 優化
select id from t with(index(索引名)) where num = @num;
- 應儘量避免使用在where語句中對字段進行表達式操作,將導致全表掃描
select * from user where id/2= 100;
# 改爲
select * from user where id = 100 * 2;
- 儘量避免在where子句中對字段進行函數操作,將導致全表掃描
select id from t where substring(name,1,3) = 'abc';
# name以abc開頭的id 可以改爲
select id from t where name like 'abc%';
- 不要再where語句的左邊進行 = 函數或算術運算的操作,否則會導致無法正確使用索引。
9.11 優化OR條件
對於包含or的查詢子句,如果要利用索引,則or之間的每個列都必須有索引,如果有一個列沒有索引,將導致所有索引失效,而且不能使用複合索引,如果沒有索引要考慮增加索引
select * from emp where id = 30 or id = 10;
優化
select * from emp where id = 30 union select * from emp where id = 10;