国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

關(guān)于數(shù)據(jù)庫SQL優(yōu)化

這篇具有很好參考價值的文章主要介紹了關(guān)于數(shù)據(jù)庫SQL優(yōu)化。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

關(guān)于數(shù)據(jù)庫SQL優(yōu)化

?

簡介

  1. 在項目上線初期,業(yè)務(wù)數(shù)據(jù)量相對較少,SQL的執(zhí)行效率對程序運行效率的影響可能不太明顯,因此開發(fā)和運維人員可能無法判斷SQL對程序的運行效率有多大。但隨著時間的積累,業(yè)務(wù)數(shù)據(jù)量的增多,SQL的執(zhí)行效率對程序的運行效率的影響逐漸增大,此時對SQL的優(yōu)化就很有必要。
  2. 優(yōu)化SQL可以使其更有效地使用索引、減少硬盤I/O等,從而提高程序的運行效率。
  3. 優(yōu)化SQL可以使其更好地利用緩存,從而降低程序的響應(yīng)時間。
  4. 優(yōu)化SQL可以使其更好地處理大數(shù)據(jù)量,從而減少程序的運行時間。
  5. 優(yōu)化SQL可以使其更符合程序的業(yè)務(wù)需求,從而提高程序的性能和用戶體驗。

一、查詢SQL盡量不要使用select *,而是具體字段。

1、反例

select * from emp

2、正例

select id,sex,user_name,salary from emp

3、理由

  • 使用 * 號是因為使用 * 號會查詢出表中所有列的數(shù)據(jù),
  • 查詢所有列可能會導(dǎo)致性能問題,特別是當(dāng)表中包含大量列時,查詢所有列可能會導(dǎo)致查詢速度變慢。
  • 查詢所有列可能會導(dǎo)致數(shù)據(jù)冗余,特別是當(dāng)表中包含多個關(guān)聯(lián)表時,查詢所有列可能會導(dǎo)致返回大量重復(fù)數(shù)據(jù)。
  • 指定需要查詢的列可以使查詢結(jié)果更易于理解和維護,特別是當(dāng)表中包含大量列時,指定需要查詢的列可以使查詢結(jié)果更加清晰和易于理解。

?二、where中使用默認(rèn)值代替NULL

說明:

? ? ? ? 為了方便 我就使用* 代替了。

1、反例

select * from emp where  salary is not null

2、正例

select * from emp  where  salary > 0

3、理由

  • 提高查詢效率:在 WHERE 子句中使用 NULL 值需要進行 IS NULL 或 IS NOT NULL 的判斷,這需要額外的計算成本。而使用默認(rèn)值 0 代替 NULL 值可以使查詢條件更加簡單明確,避免進行額外的判斷,從而提高查詢效率。
  • 避免 NULL 值帶來的問題:NULL 值具有特殊的語義,即無法進行任何比較。因此,在 WHERE 子句中使用 NULL 值可能會導(dǎo)致查詢結(jié)果不準(zhǔn)確或無法執(zhí)行。使用默認(rèn)值 0 代替 NULL 值可以避免這種情況,確保查詢結(jié)果的準(zhǔn)確性和可執(zhí)行性。
  • 提高代碼可讀性和可維護性:使用默認(rèn)值 0 代替 NULL 值可以使代碼更加清晰易懂,提高可讀性。同時,在修改查詢條件時,使用默認(rèn)值 0 也可以避免忘記處理 NULL 值的情況,提高代碼的可維護性。

三、避免在where子句中使用 or 來連接條件

1、反例

select * from emp  where id = 1 or salary = 2500.10
  • 使用 or?可能會引起索引失效,從而進行全表掃描
  • or??操作符連接的兩個條件只要有一個條件成立,就會返回相應(yīng)的結(jié)果集。因此,當(dāng)使用 where id=1 or salary=2500.10?進行查詢時,如果 id 字段上有索引,但 salary 字段上沒有索引,那么查詢引擎會優(yōu)先使用 id 索引進行查詢,因為 id 字段上的條件一定成立。但如果要查詢的 salary 值不在 id 索引的范圍內(nèi),那么查詢引擎可能需要進行全表掃描或放棄使用索引,導(dǎo)致 id 索引失效。

2、正例

select * from emp  where id = 1
union all
select * from emp  where salary = 2500.10
  • 使用 UNION ALL 用于將兩個SELECT語句的結(jié)果合并在一起,形成一個結(jié)果集。
  • 與UNION不同的是,UNION ALL不會去除重復(fù)的數(shù)據(jù)行,而是將所有符合條件的數(shù)據(jù)行都列出來。
  • 在 salary 字段上創(chuàng)建索引,這樣查詢引擎就可以使用兩個字段上的索引來優(yōu)化查詢,提高查詢性能。
  • 使用 UNION ALL 操作符將兩個查詢結(jié)果合并,這樣可以避免使用 OR 操作符,從而避免 id 索引失效的問題。

四、盡量使用數(shù)值替代字符串類型

1、正例

主鍵(id):primary key優(yōu)先使用數(shù)值類型int,tinyint。

性別(sex)?:0代表女,1代表男,數(shù)據(jù)庫沒有布爾類型,mysql推薦使用tinyint。

2、理由

  • 引擎在處理查詢和連接時會逐個比較字符串中每一個字符,而對于數(shù)字型而言只需要比較一次就夠了,因此數(shù)值類型可以大大提高查詢和連接的性能。
  • 字符串和數(shù)字之間的比較需要進行隱式的類型轉(zhuǎn)換,這會導(dǎo)致查詢性能的降低。
  • 索引的優(yōu)缺點之一是可以加速表與表之間的連接,特別是在實現(xiàn)數(shù)據(jù)的參考完整性方面特別有意義。通過使用數(shù)值類型,可以在創(chuàng)建索引時提高查詢性能和連接性能。
  • 在使用分組和排序字句進行數(shù)據(jù)檢索時,數(shù)值類型可以顯著減少查詢中分組和排序的時間。

五、使用varchar代替char

1、反例

`address` char(100) DEFAULT NULL COMMENT '地址'
  • sql中使用char(100)作為數(shù)據(jù)類型有一些缺點。首先,char(100)會占用更多的磁盤空間,因為每個字符都需要固定長度的存儲空間。其次,使用char(100)時,如果存儲的字符串長度小于100個字符,會出現(xiàn)浪費存儲空間的情況。
  • 另外,如果某些字段涉及到文件排序或者基于磁盤的臨時表時,使用char(100)可能會消耗更多的內(nèi)存,因為固定長度的字符型數(shù)據(jù)在內(nèi)存中是連續(xù)的空間。因此,在使用char(100)時需要考慮這些缺點,并根據(jù)實際需求選擇更適合的數(shù)據(jù)類型。

2、正例

`address` varchar(100) DEFAULT NULL COMMENT '地址'
  • 存儲靈活:相比于固定長度的數(shù)據(jù)類型,varchar(100)可以存儲長度為100的字符串,也可以存儲長度小于100的字符串,或者不存儲任何字符,因此可以更加靈活地處理數(shù)據(jù)。
  • 內(nèi)存消耗較?。簩τ谳^短的字符串,使用varchar(100)可以減少內(nèi)存消耗。例如,如果需要存儲一個長度為10的字符串,使用固定長度的數(shù)據(jù)類型需要11個字節(jié)的內(nèi)存空間,而使用varchar(100)只需要2個字節(jié)的內(nèi)存空間。
  • 可以避免浪費磁盤空間:如果使用固定長度的數(shù)據(jù)類型存儲長度不足的值,會浪費一些磁盤空間。而使用varchar(100)可以根據(jù)實際需要使用或浪費較少的磁盤空間。
  • 可以提高查詢性能:在某些情況下,使用varchar(100)可以提高查詢性能。例如,如果一個表中的某些列經(jīng)常需要被查詢,而這些列使用固定長度的數(shù)據(jù)類型可能會浪費一些內(nèi)存空間,從而導(dǎo)致查詢性能下降。而使用varchar(100)可以根據(jù)實際情況使用更少的內(nèi)存空間,從而提高查詢性能。

六、char與varchar2的區(qū)別

1、CHAR的長度是固定的,VARCHAR2的長度是可以變化的。

  • 長度固定 vs 長度可變:CHAR的長度是固定的,而VARCHAR2的長度是可以變化的。例如,存儲字符串“101”,對于CHAR(10),表示你存儲的字符將占10個字節(jié)(包括7個空字符),而同樣的VARCHAR2(10)則只占用3個字節(jié)的長度。
  • 存儲空間:CHAR比VARCHAR2更節(jié)省存儲空間,因為CHAR類型在數(shù)據(jù)庫中以空格填充,而VARCHAR2則不會。但是,VARCHAR2在效率上比CHAR稍差一點。
  • 性能:CHAR類型在某些方面比VARCHAR2類型稍快,因為它具有固定的長度,因此在處理和搜索數(shù)據(jù)時,它可以更快地定位和讀取。

2、什么時候選擇CHAR什么時候選擇VARCHAR2

  • 存儲需求:如果需要存儲的字符數(shù)據(jù)長度固定且長度較小,則使用CHAR更為節(jié)省空間。如果數(shù)據(jù)長度變化范圍較大,或者長度較小,則使用VARCHAR2更為節(jié)省空間。
  • 性能需求:如果應(yīng)用程序需要快速高效的查詢和搜索數(shù)據(jù),并且對數(shù)據(jù)的長度有要求,則使用CHAR可能更合適。如果對性能要求不高,而對數(shù)據(jù)長度和變化范圍有要求,則更適合使用VARCHAR2。

注意: 在使用VARCHAR2時,如果一個列經(jīng)常被修改,并且每次修改的數(shù)據(jù)長度不同,這可能會導(dǎo)致Row Migration(行遷移)現(xiàn)象,這可能會影響數(shù)據(jù)庫性能并增加I/O負(fù)擔(dān)。在這種情況下,使用CHAR可能更好。

CHAR中還會自動補齊空格,因為你INSERT到一個CHAR字段自動補充了空格的,但是SELECT后空格沒有刪除,因此CHAR類型查詢的時候一定要記得使用TRIM函數(shù)去除字符串兩端的空格。

3、如何使用TRIM

在查詢CHAR類型的列時,如果要使用TRIM函數(shù)去除字符串兩端的空格,可以使用以下語法:

select * from emp  where TRIM(text) = 'csdn';
  • emp是要查詢的表名,text是要查詢的CHAR類型的列名,csdn是要匹配的字符串。TRIM函數(shù)將去除csdn中字符串兩端的空格,并返回與csdn相等的唯一值。
  • 需要注意:使用TRIM函數(shù)可能會影響查詢性能。如果查詢速度非常重要,則可以考慮將CHAR類型的列轉(zhuǎn)換為VARCHAR2類型,因為VARCHAR2類型會自動去除字符串兩端的空格。但是,這種方法可能會導(dǎo)致存儲空間的浪費。

七、避免在where子句中使用!=或<> 等操作符

1、反例

select * from emp where salary !=2500.10

select * from emp where salary <>2500.10

2、理由

  • 當(dāng)查詢語句中使用 IS NULL 或 IS NOT NULL 運算符進行空值判斷時,數(shù)據(jù)庫無法利用索引進行查詢,因為索引只是一種用于快速查找數(shù)據(jù)的數(shù)據(jù)結(jié)構(gòu),無法判斷數(shù)據(jù)是否為空。此時,數(shù)據(jù)庫需要遍歷整個表來查找符合條件的行,從而導(dǎo)致索引失效。
  • 即使在查詢語句中使用了 = 或 > 等運算符進行等值或范圍查詢,但如果查詢條件中包含了一個未使用索引的列,也會導(dǎo)致索引失效。

? 3、舉例

select * from emp  where user_name ='choudidi'  and  salary is not null;
  • 在這個查詢語句中,user_name 列使用了索引,但 salary 列沒有使用索引。因此,即使 user_name 列的條件滿足,數(shù)據(jù)庫仍然需要遍歷整個表來查找符合條件的行,從而導(dǎo)致索引失效。

八、inner join 、left join、right join,優(yōu)先使用inner join

  • 優(yōu)先使用INNER JOIN的原因是其性能相對更好。INNER JOIN是等值連接,只保留兩張表中完全匹配的結(jié)果集,而LEFT JOIN和RIGHT JOIN會返回左表或右表的所有行,即使在另一張表中沒有匹配的記錄。
  • 因此,如果使用LEFT JOIN或RIGHT JOIN,可能會導(dǎo)致返回的數(shù)據(jù)量較大,從而影響查詢性能。
  • INNER JOIN將數(shù)據(jù)集的較小數(shù)據(jù)驅(qū)動,而LEFT JOIN和RIGHT JOIN則將較大的數(shù)據(jù)集驅(qū)動,這也是MySQL優(yōu)化原則之一。
  • 小表驅(qū)動大表,小的數(shù)據(jù)集驅(qū)動大的數(shù)據(jù)集,從而讓性能更優(yōu)。

九、提高group by語句的效率

1、反例

select department, avg(salary) from emp 
group by department
having department ='1' or department = '3';
  • ?先分組,再過濾

2、正例

select department,avg(salary) from emp 
where department ='1' or department = '3' 
group by department;
  • 先過濾,后分組

  • 篩選出符合條件的記錄:where子句中的條件篩選出了部門為'1'或'3'的員工記錄,只對符合條件的記錄進行后續(xù)計算。

  • 按部門分組:group by子句將結(jié)果集按照部門進行分組,這樣每個部門的數(shù)據(jù)都會單獨計算平均值,避免了將所有記錄混合在一起計算平均值的情況。

十、清空表時優(yōu)先使用truncate?

  • 速度更快:truncate比delete更快,因為它不會記錄在日志中,也不需要在事務(wù)日志中為所刪除的每行記錄一項。
  • 占用的資源更少:truncate通過釋放存儲表數(shù)據(jù)所用的數(shù)據(jù)頁來刪除數(shù)據(jù),而不是在事務(wù)日志中記錄頁的釋放,而delete語句每次刪除一行,并在事務(wù)日志中為所刪除的每行記錄一項。
  • 保持表結(jié)構(gòu)及其列、約束、索引等不變:truncate刪除表中的所有行,但表結(jié)構(gòu)及其列、約束、索引等保持不變。新行標(biāo)識所用的計數(shù)值重置為該列的種子。如果要保留標(biāo)識計數(shù)值,請改用delete。如果要刪除表定義及其數(shù)據(jù),請使用drop table語句。
  • 不適用于參與了索引視圖的表:truncate不能用于參與了索引視圖的表,而delete可以。
  • 不激活觸發(fā)器:truncate不會激活觸發(fā)器,而delete會。truncate不會激活觸發(fā)器的原因是它不會記錄各行的日志刪除操作。由于truncate操作不會記錄在事務(wù)日志中,所以它不會激活delete觸發(fā)器。

十一、操作delete或者update語句,加limit或使用循環(huán)分批次刪除

  • 降低數(shù)據(jù)庫負(fù)載:一次性刪除(或更新)大量數(shù)據(jù)會對數(shù)據(jù)庫性能造成較大的壓力,導(dǎo)致其他操作變慢或阻塞。分批次刪除可以降低數(shù)據(jù)庫負(fù)載,保證其他操作的正常運行。
  • 提高數(shù)據(jù)安全性:刪除或更新大量數(shù)據(jù)時,如果不小心出現(xiàn)錯誤操作,可能會導(dǎo)致數(shù)據(jù)丟失或不可恢復(fù)。分批次刪除可以降低操作風(fēng)險,即使不小心刪除也可以通過binlog日志恢復(fù)進行回滾操作。
  • 便于代碼實現(xiàn):一次性刪除大量數(shù)據(jù)可能會導(dǎo)致內(nèi)存溢出或其他異常情況,使用循環(huán)分批次刪除可以避免這些問題。同時,使用循環(huán)分批次刪除也可以降低代碼復(fù)雜度,提高代碼可讀性和可維護性。
  • 鎖表:一次性大量刪除太多數(shù)據(jù),可能造成鎖表,會有l(wèi)ock wait timeout exceed的錯誤,所以建議分批操作。
  • 減少鎖定時間:刪除或更新數(shù)據(jù)時,數(shù)據(jù)庫會對相關(guān)行進行鎖定,確保數(shù)據(jù)一致性。如果一次性刪除大量數(shù)據(jù),鎖定時間會較長,影響其他操作。而分批次刪除可以縮短鎖定時間,提高并發(fā)性能。

1、正例

1、使用limit限制刪除數(shù)量

delete from emp limit 1000;
-- 或
delete from emp where 條件 limit 1000;  # 每次刪除 1000 行數(shù)據(jù)
-- 或者
UPDATE emp SET column1 = value1, column2 = value2, ... WHERE condition LIMIT 1000;  # 每次更新 1000 行數(shù)據(jù)
  • ?可以在delete或update語句中添加limit關(guān)鍵字,指定每次刪除的數(shù)據(jù)量。列如以上SQL每次刪除1000條數(shù)據(jù):

2、使用循環(huán)分批次刪除

CREATE DEFINER = `root` @`localhost` PROCEDURE `P_xiao_jian` () BEGIN
	DECLARE
		i INT DEFAULT 1;#Routine body goes here...
	START TRANSACTION;
	
	SET @counter = 1;
	WHILE
			@counter <= 1000 DO DELETE FROM order_for_goods WHERE order_id >= @counter;
		
		SET @counter = @counter + 1;
		
	END WHILE;
	COMMIT;

END
  1. 定義一個名為 P_xiao_jian 的存儲過程,使用 CREATE PROCEDURE 語句創(chuàng)建。
  2. 定義一個名為 @counter 的整型變量,并初始化為 1。
  3. 使用 START TRANSACTION 語句開始一個事務(wù)。
  4. 使用 WHILE 循環(huán),循環(huán)條件為 @counter 小于等于 1000。
  5. 在循環(huán)體內(nèi),使用 DELETE FROM 語句刪除 order_for_goods 表中 order_id 大于等于當(dāng)前循環(huán)變量 @counter 的所有記錄。
  6. 循環(huán)結(jié)束后,使用 COMMIT 語句提交事務(wù)。
  7. 使用 END 語句結(jié)束存儲過程的定義。
    ?

十二、UNION操作符

  • UNION操作符用于將兩個或多個SELECT語句的結(jié)果集合并成一個結(jié)果集。
select user_name,salary from emp 
union
select departmentname from department
  • union在進行表連接后會篩選掉重復(fù)的記錄,所以在表連接后會對所產(chǎn)生的結(jié)果集進行排序運算,刪除重復(fù)的記錄再返回結(jié)果。
  • 在運行時先取出兩個表的結(jié)果,再用排序空間進行排序刪除重復(fù)的記錄,最后返回結(jié)果集,如果表數(shù)據(jù)量大的話可能會導(dǎo)致用磁盤進行排序。
    ?

推薦:采用union all操作符替代union,因為union all操作只是簡單的將兩個結(jié)果合并后就返回。

十三、批量插入性能提升

1、反例

  • 多條提交
insert into emp (id,user_name) values(1,'提交1條');

insert into emp (id,user_name) values(2,'提交2條');

2、正例

  • 批量提交
insert into emp (id,user_name) values(1,'提交1條'),(2,'提交2條');
  • 當(dāng)執(zhí)行INSERT、UPDATE或DELETE語句默認(rèn)SQL有事務(wù)控制,導(dǎo)致每條都需要事務(wù)開啟和事務(wù)提交,而批量處理是一次事務(wù)開啟和提交,效率提升明顯,達到一定量級,效果顯著。

十四、表連接不宜太多,索引不宜太多,建議5個以內(nèi)

1、表連接不宜太多原因

  • 關(guān)聯(lián)的表個數(shù)越多,編譯的時間和開銷也就越大。
  • 每次關(guān)聯(lián)內(nèi)存中都生成一個臨時表,應(yīng)該把連接表拆開成較小的幾個執(zhí)行,可讀性更高。
  • 如果一定需要連接很多表才能得到數(shù)據(jù),那么意味著這是個不理想的的設(shè)計。
  • 可以查看阿里規(guī)范手冊,其中包含一條建議多表聯(lián)查三張表以下
  • 通常情況下,建議將表連接的數(shù)量控制在5個以內(nèi),這樣可以提高查詢的效率和性能。如果需要連接更多的表,可以考慮對查詢進行拆分或重構(gòu),以減少連接的數(shù)量。此外,還可以使用索引、臨時表、視圖等技術(shù)來優(yōu)化查詢性能。

2、索引不宜太多原因

  • 增加額外的開銷:索引需要維護,包括更新、插入和刪除等操作,而這些操作都會增加額外的開銷。特別是對于頻繁更新的表,索引可能會成為性能瓶頸。
  • 占用磁盤空間:索引需要存儲在磁盤上,因此會增加磁盤空間的占用。過多的索引可能會使查詢變得緩慢,因為數(shù)據(jù)量越大,查詢所花費的時間可能比表里索引的時間還要短,索引可能不會產(chǎn)生優(yōu)化效果。
  • 降低查詢效率:索引設(shè)計不合理或者缺少索引都會對數(shù)據(jù)庫性能造成不良影響。過多的索引可能會使查詢變得復(fù)雜,降低查詢效率。

十五、避免在索引列上使用內(nèi)置函數(shù)

說明:

? ? ?在索引列上使用內(nèi)置函數(shù)可能會導(dǎo)致索引失效,從而降低查詢性能。這是因為索引是為了快速訪問表中數(shù)據(jù)而創(chuàng)建的,但是內(nèi)置函數(shù)可能會改變索引列中的數(shù)據(jù),導(dǎo)致索引無法識別數(shù)據(jù)。

為了避免在索引列上使用內(nèi)置函數(shù),可以考慮以下幾種方法:

  1. 優(yōu)化查詢語句:如果必須使用內(nèi)置函數(shù),可以嘗試優(yōu)化查詢語句,以減少函數(shù)的使用次數(shù),或者使用其他方法來避免使用內(nèi)置函數(shù)。
  2. 創(chuàng)建計算列:如果必須使用內(nèi)置函數(shù),可以創(chuàng)建一個計算列,并在該列上創(chuàng)建索引。這樣,內(nèi)置函數(shù)的結(jié)果將存儲在新列中,而不是原始列中,從而避免影響索引。
  3. 創(chuàng)建視圖:如果必須使用內(nèi)置函數(shù),可以創(chuàng)建一個視圖,并在視圖中使用內(nèi)置函數(shù)。然后,在查詢中使用視圖而不是表,以避免在索引列上使用內(nèi)置函數(shù)。
  4. 更改數(shù)據(jù)類型:如果可能,將索引列的數(shù)據(jù)類型更改為適合內(nèi)置函數(shù)的類型,以避免使用內(nèi)置函數(shù)。例如,如果要在索引列上使用日期函數(shù),可以將數(shù)據(jù)類型更改為日期類型。

十六、組合索引

說明:

? ? ? ?如果查詢中排序的順序與組合索引的列順序不匹配,那么查詢效率可能會下降。這是因為數(shù)據(jù)庫無法利用索引進行排序,而只能使用其他算法進行排序,從而導(dǎo)致查詢效率下降。

create index idx_username_tel on employees (deptid,username,createtime);

select username,tel from employees  where deptid= 1 and username = 'CSDN' order by deptid,position,createtime desc; 

雖然創(chuàng)建了基于deptid、username和createtime列的索引,但是查詢條件中只使用了deptid=1和username=csdn列,沒有利用到createtime列。因此,這個查詢不能利用到基于createtime列的索引,查詢性能可能會受到影響。同時,如果表中的數(shù)據(jù)量非常大,創(chuàng)建索引可能會對系統(tǒng)的性能產(chǎn)生較大的影響。
?

十七、復(fù)合索引最左特性

說明:

? ? ? 復(fù)合索引(也稱為聯(lián)合索引)具有"最左前綴"特性。這意味著,當(dāng)查詢條件中使用了復(fù)合索引中的第一個列(最左邊的列),則該復(fù)合索引可以被使用。如果查詢條件中使用了復(fù)合索引中的多個列,則該復(fù)合索引也可以被使用,但是前提是這些列的順序必須與復(fù)合索引中的順序相同。?

1、創(chuàng)建復(fù)合索引

CREATE INDEX idx_name_age ON employees (name, age);

2、假設(shè)我們有一個查詢,需要按name和age進行排序,可以使用該復(fù)合索引(如下)

SELECT * FROM employees WHERE name = 'John' AND age = 25 ORDER BY name, age;

在這個查詢中,我們使用了復(fù)合索引中的第一個列name和第二個列age。由于這些列的順序與復(fù)合索引中的順序相同,因此該復(fù)合索引可以被使用。

3、然而,如果我們改變了查詢條件中列的順序,或者添加了其他函數(shù)或條件,可能會導(dǎo)致復(fù)合索引無法被使用(如下)

-- 復(fù)合索引無法被使用  
SELECT * FROM employees WHERE age = 25 AND name = 'John' ORDER BY name, age;  
  
-- 復(fù)合索引無法被使用  
SELECT * FROM employees WHERE SUBSTRING(name, 1, 1) = 'J' AND age = 25 ORDER BY name, age;

在第一個查詢中,我們改變了查詢條件中列的順序,因此復(fù)合索引無法被使用。在第二個查詢中,我們添加了一個函數(shù)SUBSTRING,這使得復(fù)合索引無法被使用。因此,在使用復(fù)合索引時,需要注意查詢條件中列的順序,以及是否添加了任何函數(shù)或條件。?

十八、優(yōu)化like語句

1、反例

select * from emp where user_name like '%王' (不使用索引)

select * from emp where user_name like '%王%' (不使用索引)

2、正例

select * from emp where user_name like '王%' (使用索引) 。

3、理由

  • 使用前綴匹配,當(dāng)你知道要搜索的字符串具有某個特定的前綴時,可以使用前綴匹配來提高查詢效率。例如,如果你知道要搜索的名字都以 "張" 開頭,可以使用 LIKE '張%'。
  • 首先盡量避免模糊查詢,如果必須使用,不采用全模糊查詢,也應(yīng)盡量采用右模糊查詢, 即like '...%',是會使用索引的,左模糊like '%...'無法直接使用索引,但可以利用reverse + function index的形式,變化成 like '...%'。
  • 全模糊查詢是無法優(yōu)化的,一定要使用的話建議使用搜索引擎。

reverse + function index的形式如下:

SELECT * FROM emp WHERE LEFT(user_name, 1) LIKE '肖%';
  • 這將返回名字以 "肖" 開頭的所有名字。在這個語句中,LEFT(user_name, 1) 提取名字左側(cè)的第一個字符,并將其與 '肖%' 進行比較。注意,這里使用了 % 通配符來表示任意字符(包括 0 個字符),因此 '肖%' 表示以 "肖" 開頭的任意字符串。

十九、使用explain分析你SQL執(zhí)行計劃

1、type類型

  • system:表僅有一行,基本用不到;
  • const:表最多一行數(shù)據(jù)配合,主鍵查詢時觸發(fā)較多;
  • eq_ref:對于每個來自于前面的表的行組合,從該表中讀取一行。這可能是最好的聯(lián)接類型,除了const類型;
  • ref:對于每個來自于前面的表的行組合,所有有匹配索引值的行將從這張表中讀??;
  • range:只檢索給定范圍的行,使用一個索引來選擇行。當(dāng)使用=、<>、>、>=、<、<=、IS NULL、<=>、BETWEEN或者IN操作符,用常量比較關(guān)鍵字列時,可以使用range;
  • index:該聯(lián)接類型與ALL相同,除了只有索引樹被掃描。這通常比ALL快,因為索引文件通常比數(shù)據(jù)文件??;
  • all:全表掃描;
  • 性能排名:system > const > eq_ref > ref > range > index > all。
  • 實際sql優(yōu)化中,最后達到ref或range級別。

2、Extra常用關(guān)鍵字

  • Using index:只從索引樹中獲取信息,而不需要回表查詢;
  • Using where:WHERE子句用于限制哪一個行匹配下一個表或發(fā)送到客戶。除非你專門從表中索取或檢查所有行,如果Extra值不為Using where并且表聯(lián)接類型為ALL或index,查詢可能會有一些錯誤。需要回表查詢。
  • Using temporary:mysql常建一個臨時表來容納結(jié)果,典型情況如查詢包含可以按不同情況列出列的GROUP BY和ORDER BY子句時;
    ?

二十、其他SQL優(yōu)化方式

1、設(shè)計表的時候,所有表和字段都添加相應(yīng)的注釋。

2、SQL書寫格式,關(guān)鍵字大小保持一致,使用縮進。

3、修改或刪除重要數(shù)據(jù)前,要先備份。

4、很多時候用 exists 代替 in 是一個好的選擇

5、where后面的字段,留意其數(shù)據(jù)類型的隱式轉(zhuǎn)換。

  • 在SQL中,當(dāng)在WHERE子句中指定條件時,如果條件中的字段類型與查詢中指定的字段類型不匹配,SQL可能會進行隱式的類型轉(zhuǎn)換,也稱為“隱式轉(zhuǎn)換”或“隱式類型轉(zhuǎn)換”。
  • 例如,如果一個字段是一個日期類型,而條件中指定的值是一個字符串類型,SQL可能會嘗試將字符串值轉(zhuǎn)換為日期類型。同樣,如果一個字段是一個數(shù)值類型,而條件中指定的值是一個字符串類型,SQL可能會嘗試將字符串值轉(zhuǎn)換為數(shù)值類型。
  • 這種隱式類型轉(zhuǎn)換在某些情況下可能是有用的,但在其他情況下可能會導(dǎo)致錯誤的結(jié)果。因此,建議在編寫查詢時始終顯式指定要比較的值和字段的類型,以避免出現(xiàn)意外的問題。

如:

SELECT * FROM emp WHERE NAME=12345
  • 因為不加單引號時,是字符串跟數(shù)字的比較,它們類型不匹配
  • MySQL會做隱式的類型轉(zhuǎn)換,把它們轉(zhuǎn)換為數(shù)值類型再做比較

6、盡量把所有列定義為NOT NULL

  • NOT NULL列更節(jié)省空間,NULL列需要一個額外字節(jié)作為判斷是否為 NULL的標(biāo)志位。
  • NULL列需要注意空指針問題,NULL列在計算和比較的時候,需要注意空指針問題。

7、偽刪除設(shè)計

8、數(shù)據(jù)庫和表的字符集盡量統(tǒng)一使用UTF8

  • 可以避免亂碼問題。
  • 可以避免,不同字符集比較轉(zhuǎn)換,導(dǎo)致的索引失效問題。

9、select count(*) from table;

  • 這樣不帶任何條件的count會引起全表掃描,并且沒有任何業(yè)務(wù)意義,是一定要杜絕的。

10、避免在where中對字段進行表達式操作

  • SQL解析時,如果字段相關(guān)的是表達式就進行全表掃描
  • 字段干凈無表達式,索引生效

11、關(guān)于臨時表

  • 避免頻繁創(chuàng)建和刪除臨時表,以減少系統(tǒng)表資源的消耗;
  • 在新建臨時表時,如果一次性插入數(shù)據(jù)量很大,那么可以使用 select into 代替 create table,避免造成大量 log;
  • 如果數(shù)據(jù)量不大,為了緩和系統(tǒng)表的資源,應(yīng)先create table,然后insert;
  • 如果使用到了臨時表,在存儲過程的最后務(wù)必將所有的臨時表顯式刪除。先 truncate table ,然后 drop table ,這樣可以避免系統(tǒng)表的較長時間鎖定。

12、索引不適合建在有大量重復(fù)數(shù)據(jù)的字段上,比如性別,排序字段應(yīng)創(chuàng)建索引

13、去重distinct過濾字段要少

  • 帶distinct的語句占用cpu時間高于不帶distinct的語句
  • 當(dāng)查詢很多字段時,如果使用distinct,數(shù)據(jù)庫引擎就會對數(shù)據(jù)進行比較,過濾掉重復(fù)數(shù)據(jù)
  • 然而這個比較、過濾的過程會占用系統(tǒng)資源,如cpu時間

14、盡量避免大事務(wù)操作,提高系統(tǒng)并發(fā)能力

15、所有表必須使用Innodb存儲引擎

  • Innodb「支持事務(wù),支持行級鎖,更好的恢復(fù)性」,高并發(fā)下性能更好,所以呢,沒有特殊要求(即Innodb無法滿足的功能如:列存儲,存儲空間數(shù)據(jù)等)的情況下,所有表必須使用Innodb存儲引擎。

16、盡量避免使用游標(biāo)文章來源地址http://www.zghlxwxcb.cn/news/detail-481007.html

  • 因為游標(biāo)的效率較差,如果游標(biāo)操作的數(shù)據(jù)超過1萬行,那么應(yīng)該考慮改寫。

到了這里,關(guān)于關(guān)于數(shù)據(jù)庫SQL優(yōu)化的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費用

相關(guān)文章

  • 【MySQL 數(shù)據(jù)庫】7、SQL 優(yōu)化

    【MySQL 數(shù)據(jù)庫】7、SQL 優(yōu)化

    ① 批量插入數(shù)據(jù) ② 手動控制事務(wù) ③ 主鍵順序插入,性能要高于亂序插入 主鍵亂序插入 : 8 1 9 21 88 2 4 15 89 5 7 3 主鍵順序插入 : 1 2 3 4 5 7 8 9 15 21 88 89 【☆】 】 ① 如果需要一次性插入大批量數(shù)據(jù)(百萬級別),使用 insert 語句插入性能 很低 ② 可使用 MySQL 數(shù)據(jù)庫提供的 loa

    2024年02月08日
    瀏覽(33)
  • SQL Server 數(shù)據(jù)庫優(yōu)化分享

    ? ? ? ?隨著數(shù)據(jù)量和業(yè)務(wù)復(fù)雜性的增加,數(shù)據(jù)庫優(yōu)化變得越來越重要。通過對 SQL Server 數(shù)據(jù)庫進行優(yōu)化,您可以提高查詢性能、減少資源消耗,從而改善整體系統(tǒng)性能。以下是一些優(yōu)化技巧,可幫助您實現(xiàn)更高效、更可靠的數(shù)據(jù)庫操作。 使用恰當(dāng)?shù)乃饕?索引是一種提供快

    2024年02月11日
    瀏覽(89)
  • 數(shù)據(jù)庫優(yōu)化:探索 SQL 中的索引

    數(shù)據(jù)庫優(yōu)化:探索 SQL 中的索引

    推薦:使用 NSDT場景編輯器 助你快速搭建可編輯的3D應(yīng)用場景 在一本書中搜索特定主題時,我們將首先訪問索引頁面(該頁面位于該書的開頭),并找到包含我們感興趣的主題的頁碼?,F(xiàn)在,想象一下在沒有索引頁的書中找到特定主題是多么不方便。為此,我們必須搜索書中

    2024年02月14日
    瀏覽(96)
  • 【數(shù)據(jù)庫】sql優(yōu)化有哪些?從query層面和數(shù)據(jù)庫層面分析

    【數(shù)據(jù)庫】sql優(yōu)化有哪些?從query層面和數(shù)據(jù)庫層面分析

    這類型問題可以稱為:Query Optimization,從清華AI4DB的paper list中,該類問題大致可以分為: Query Rewriter Cardinality Estimation Cost Estimation Plan Optimization 從中文的角度理解那就是: 查詢重寫 基數(shù)估計 成本估計 執(zhí)行計劃優(yōu)化 可以發(fā)現(xiàn),這類型的優(yōu)化問題,大多數(shù)從sql本身,或者說從

    2024年01月17日
    瀏覽(97)
  • 百萬級sql server數(shù)據(jù)庫優(yōu)化案例分享

    百萬級sql server數(shù)據(jù)庫優(yōu)化案例分享

    ????????在我們的IT職業(yè)生涯中,能有一次百萬級的數(shù)據(jù)庫的優(yōu)化經(jīng)歷是很難得的,如果你遇到了恭喜你,你的職業(yè)生涯將會更加完美,如果你遇到并解決了,那么一定足夠你炫耀很多年。 ? ? ? ? 這里我將要分享一次完美的百萬級數(shù)據(jù)庫優(yōu)化經(jīng)歷,希望能給在IT行業(yè)的小

    2024年02月17日
    瀏覽(92)
  • 玩轉(zhuǎn)MySQL數(shù)據(jù)庫之SQL優(yōu)化之慢查詢

    本系列為:MySQL數(shù)據(jù)庫詳解,為千鋒資深教學(xué)老師獨家創(chuàng)作,致力于為大家講解清晰MySQL數(shù)據(jù)庫相關(guān)知識點,含有豐富的代碼案例及講解。如果感覺對大家有幫助的話,可以【關(guān)注】持續(xù)追更~ 文末有本文重點總結(jié),技術(shù)類問題,也歡迎大家和我們溝通交流! 從今天開始本系列

    2024年02月06日
    瀏覽(98)
  • MySQL數(shù)據(jù)庫第十四課--------sql優(yōu)化---------層層遞進

    MySQL數(shù)據(jù)庫第十四課--------sql優(yōu)化---------層層遞進

    ?? ?????????????????????? ??? 作者介紹: ???? ?? ?????????????? ?? ??作者id:老秦包你會, ?? 簡單介紹:?????????????????????????????? 喜歡學(xué)習(xí)C語言和python等編程語言,是一位愛分享的博主,有興趣的小可愛可以來互討 ????

    2024年02月12日
    瀏覽(99)
  • 【JaveWeb教程】(17) MySQL數(shù)據(jù)庫開發(fā)之 MySQL簡介、安裝、數(shù)據(jù)類型、SQL通用語法 詳細(xì)代碼示例講解

    【JaveWeb教程】(17) MySQL數(shù)據(jù)庫開發(fā)之 MySQL簡介、安裝、數(shù)據(jù)類型、SQL通用語法 詳細(xì)代碼示例講解

    在我們講解SpringBootWeb基礎(chǔ)知識(請求響應(yīng)案例)的時候,我們講到在web開發(fā)中,為了應(yīng)用程序職責(zé)單一,方便維護,我們一般將web應(yīng)用程序分為三層,即:Controller、Service、Dao 。 之前我們的案例中,是這樣子的請求流程:瀏覽器發(fā)起請求,先請求Controller;Controller接收到請求之

    2024年01月25日
    瀏覽(36)
  • 【MySQL】MySQL PHP 語法,PHP MySQL 簡介,查詢,下載 MySQL 數(shù)據(jù)庫, SQL 教程

    【MySQL】MySQL PHP 語法,PHP MySQL 簡介,查詢,下載 MySQL 數(shù)據(jù)庫, SQL 教程

    作者簡介: 辭七七,目前大一,正在學(xué)習(xí)C/C++,Java,Python等 作者主頁: 七七的個人主頁 文章收錄專欄: 七七的閑談 歡迎大家點贊 ?? 收藏 ? 加關(guān)注哦!???? MySQL 可應(yīng)用于多種語言,包括 PERL, C, C++, JAVA 和 PHP,在這些語言中,MySQL 在 PHP 的 web 開發(fā)中是應(yīng)用最廣泛。 我們

    2024年02月11日
    瀏覽(28)
  • 關(guān)于JAVA Maven項目連接mysql數(shù)據(jù)庫

    ? 本文作為個人學(xué)習(xí)筆記 此處使用8.0.28版本,關(guān)于mysql更多依賴版本查閱:https://mvnrepository.com/artifact/com.mysql/mysql-connector-j 1、指定驅(qū)動器 本部分指定jdbc驅(qū)動器類名,使用Class.forName()以加載數(shù)據(jù)庫驅(qū)動程序 2、指定數(shù)據(jù)庫 本部分指定所需數(shù)據(jù)庫的url鏈接,(注:在測試過程中

    2024年04月12日
    瀏覽(19)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包