sql調(diào)優(yōu)

  • 使用 WHERE 子句等過濾條件,減少返回結(jié)果集的數(shù)據(jù)量柠偶。
  • 盡可能在關(guān)聯(lián)前進行數(shù)據(jù)過濾情妖,減少關(guān)聯(lián)操作。
  • 避免使用 SELECT *诱担,只選擇你需要的字段毡证,減少數(shù)據(jù)傳輸量

eg 假設(shè)有一個訂單管理系統(tǒng),需要優(yōu)化以下 SQL 查詢:

SELECT * FROM orders 
JOIN customers ON orders.customer_id = customers.id 
WHERE orders.order_date > '2022-01-01'

加入訂單表 orders 和客戶表 customers 很可能都包含大量數(shù)據(jù)蔫仙,我們可以首先嘗試在WHERE 子句中加入更多的過濾條件料睛,例如根據(jù)地區(qū)、訂單狀態(tài)等摇邦,以減少返回結(jié)果集的數(shù)據(jù)量恤煞。

eg 假設(shè)有兩張表,一張是用戶表(User)涎嚼,另一張是訂單表(Order)阱州。用戶表中存儲了用戶的基本信息,訂單表中存儲了用戶的訂單信息法梯,兩張表通過用戶ID進行關(guān)聯(lián)苔货。

當(dāng)需要查詢所有在過去一周內(nèi)下過訂單的活躍用戶信息時,為了減少關(guān)聯(lián)操作并提高性能立哑,可以先從訂單表中篩選出在過去一周內(nèi)下過訂單的用戶ID夜惭,然后再根據(jù)這些用戶ID去查詢用戶表中的用戶信息

SELECT u.*
FROM User u
WHERE u.user_id IN (
    SELECT DISTINCT o.user_id
    FROM `Order` o
    WHERE o.order_date >= DATE_SUB(NOW(), INTERVAL 1 WEEK)
);

比對操作:避免了直接對兩張表中的數(shù)據(jù)進行比對操作,因為通過子查詢方式铛绰,我們可以先篩選出滿足條件的數(shù)據(jù)再進行查詢诈茧,避免了在關(guān)聯(lián)階段進行大量的比對操作。

  • 確保查詢的字段上建立了索引捂掰,并保證索引的有效性敢会。
  • 優(yōu)化 SQL 查詢語句中的關(guān)聯(lián)條件曾沈,確保索引被充分利用。
SELECT * FROM orders 
JOIN customers ON orders.customer_id = customers.id 
WHERE orders.order_date > '2022-01-01'

確保 orders 表中的 order_date 字段和 customers 表中的 id 字段上都建立了索引鸥昏,提高查詢效率

  • 避免在關(guān)聯(lián)條件中對字段進行函數(shù)處理

原因:索引失效: 當(dāng)在關(guān)聯(lián)條件中對字段進行函數(shù)處理時塞俱,數(shù)據(jù)庫引擎通常無法有效使用索引。因為對字段進行函數(shù)處理后吏垮,原本的字段值發(fā)生了改變障涯,使得無法直接匹配索引中的值,從而導(dǎo)致索引失效膳汪,數(shù)據(jù)庫引擎可能無法有效地利用索引進行高效的數(shù)據(jù)查找唯蝶。

假設(shè)我們有兩個表 orders 和 customers,orders 表存儲訂單信息遗嗽,customers 表存儲客戶信息粘我,我們需要根據(jù)訂單金額和客戶等級進行關(guān)聯(lián)查詢。

首先痹换,讓我們看一下 orders 表的數(shù)據(jù)示例:

| order_id | amount |
|----------|--------|
| 1        | 100.5  |
| 2        | 200.8  |
| 3        | 300.3  |

customers 表的數(shù)據(jù)示例:

| customer_id | level |
|-------------|-------|
| 1           | 101   |
| 2           | 200   |
| 3           | 300   |

原始的 SQL 查詢可能如下涂滴,其中對訂單金額字段進行了舍入處理:

SELECT * 
FROM orders o
JOIN customers c ON ROUND(o.amount) = c.level;

為了避免在 JOIN 條件中進行函數(shù)處理,我們可以將數(shù)據(jù)處理提前到查詢前晴音。首先創(chuàng)建帶有舍入后金額的臨時表 tmp_orders:

CREATE TEMPORARY TABLE tmp_orders AS
SELECT order_id, ROUND(amount) AS rounded_amount
FROM orders;

然后基于處理后的數(shù)據(jù)進行關(guān)聯(lián)查詢:

SELECT *
FROM tmp_orders t
JOIN customers c ON t.rounded_amount = c.level;

通過這樣的處理柔纵,我們在查詢前即對訂單金額進行了舍入處理并存儲在臨時表中,避免在關(guān)聯(lián)條件中對字段進行函數(shù)處理锤躁,使得查詢更加簡潔和高效搁料。

  • 將復(fù)雜計算的結(jié)果存儲在臨時表中:

原因:1、簡化復(fù)雜邏輯: 復(fù)雜計算的結(jié)果存儲在臨時表中可以將復(fù)雜的邏輯簡化為一個簡單的數(shù)據(jù)訪問操作系羞,使得查詢語句更加清晰和易于維護郭计。
2、減少重復(fù)計算: 復(fù)雜計算通常會消耗較多的計算資源椒振,將計算結(jié)果存儲在臨時表中可以避免重復(fù)進行這些復(fù)雜計算昭伸。在后續(xù)的查詢中,直接訪問臨時表中的結(jié)果澎迎,無需重復(fù)進行耗時的計算庐杨,從而提高了查詢的效率

假設(shè)我們有一個訂單表 orders,需要從中篩選出訂單金額大于一定閾值的訂單夹供,并計算訂單金額超出閾值部分的差值灵份。

首先,讓我們看一下 orders 表的數(shù)據(jù)示例:

| order_id | amount |
|----------|--------|
| 1        | 900    |
| 2        | 1100   |
| 3        | 1200   |

原始的 SQL 查詢可能如下哮洽,計算訂單金額超出閾值部分的差值:

SELECT order_id, amount,
    CASE 
        WHEN amount > 1000 THEN amount - 1000
        ELSE 0
    END AS excess_amount
FROM orders
WHERE amount > 1000;

為了提高查詢效率填渠,我們可以將計算結(jié)果存儲在臨時表中,并后續(xù)查詢該臨時表。首先創(chuàng)建包含計算結(jié)果的臨時表 tmp_excess_orders:

CREATE TEMPORARY TABLE tmp_excess_orders AS
SELECT order_id, amount,
    CASE 
        WHEN amount > 1000 THEN amount - 1000
        ELSE 0
    END AS excess_amount
FROM orders
WHERE amount > 1000;

然后可以直接查詢這個臨時表來獲取結(jié)果:

SELECT *
FROM tmp_excess_orders;
  • 索引并不是越多越好氛什,索引固然可以提高相應(yīng)的select的效率莺葫,但同時也降低了insert 及 update 的效率

原因:索引建立越多,底層B樹結(jié)構(gòu)每個節(jié)點存儲信息就越多枪眉,插入新數(shù)據(jù)可能需要重新平衡樹結(jié)構(gòu)徙融,這可能涉及移動和重新排序節(jié)點,從而增加了操作的開銷

  • 盡量使用數(shù)字型字段瑰谜,若只含數(shù)值信息的字段盡量不要設(shè)計為字符型,這會降低查詢和連接的性能树绩,并會增加存儲開銷萨脑。

原因:
1、查詢性能提升:數(shù)字型字段比字符型字段在查詢時通常具有更好的性能饺饭。數(shù)據(jù)庫引擎可以更快地處理數(shù)字型數(shù)據(jù)的比較渤早、排序和計算操作,相比之下瘫俊,字符型數(shù)據(jù)需要更多的資源和時間來進行相同的操作鹊杖。
2、提高連接性能:在數(shù)據(jù)庫連接操作中扛芽,如果連接字段是數(shù)字型而不是字符型骂蓖,連接操作的效率通常會更高。連接操作需要比較兩個字段的值川尖,并且通過索引來加速連接操作登下;對于數(shù)字型字段,比較和索引查找的效率通常比字符型字段更高叮喳。

可能導(dǎo)致全表掃描的幾種情況:

  • 盡量避免使用in和not in被芳,在where子句中使用in和not in,引擎將放棄使用索引而進行全表掃描馍悟。
  • 盡量避免使用!=或<>操作符畔濒,在 where語句中使用!=或<>,引擎將放棄使用索引而進行全表掃描锣咒。
  • 使用like的時候要注意是否會導(dǎo)致全表掃
慢sql查詢怎么查
  1. 開啟慢查詢?nèi)罩荆?/li>

在 MySQL 數(shù)據(jù)庫中侵状,您可以通過編輯 MySQL 配置文件 my.cnf,找到并修改以下選項:

slow_query_log = 1
long_query_time = 1

slow_query_log 設(shè)為 1 以開啟慢查詢?nèi)罩居涗洠?code>long_query_time 指定慢查詢的時間閾值毅整,單位為秒壹将。這里設(shè)置為 1 表示超過 1 秒的查詢會被記錄在慢查詢?nèi)罩局小?/p>

  1. 分析慢查詢?nèi)罩?/li>

定期檢查慢查詢?nèi)罩疚募梢允褂靡韵旅钫业铰樵內(nèi)罩疚募窂剑?/p>

SHOW VARIABLES LIKE 'slow_query_log';
SHOW VARIABLES LIKE 'slow_query_log_file';

通過查看慢查詢?nèi)罩久担梢哉业綀?zhí)行時間較長的 SQL 查詢語句诽俯。

  1. 使用數(shù)據(jù)庫性能分析工具

針對慢查詢的 SQL 語句,您可以使用 MySQL 的 EXPLAIN 命令來查看查詢執(zhí)行計劃,例如:

EXPLAIN SELECT * FROM your_table WHERE condition;

這將會顯示查詢執(zhí)行計劃以及可能的性能瓶頸暴区,幫助您理解查詢的執(zhí)行方式和可能的優(yōu)化路徑闯团。

  1. 優(yōu)化 SQL 查詢

根據(jù)分析結(jié)果,您可以針對性地對慢查詢的 SQL 語句進行優(yōu)化仙粱,例如添加索引房交、重構(gòu)查詢語句、優(yōu)化數(shù)據(jù)庫配置等伐割。

面試題:
統(tǒng)計年齡在 19 到 24 歲之間年齡最大的人數(shù)

SELECT COUNT(*) AS max_age_count
FROM table_name
WHERE age >= 19 AND age <= 24
ORDER BY age DESC
LIMIT 1;
COUNT(*) 候味?

COUNT(*) 是 SQL 中用于統(tǒng)計符合特定條件的行數(shù)的聚合函數(shù)。它可以用來統(tǒng)計表中滿足條件的記錄的數(shù)量隔心。

例如白群,如果您有一個名為 "students" 的表,其中包含了學(xué)生的信息硬霍,您可以使用 COUNT(*) 來統(tǒng)計表中的記錄數(shù)量帜慢,如下所示:

SELECT COUNT(*) AS total_students
FROM students;

這將返回一個名為 "total_students" 的結(jié)果集,其中包含了表中記錄的總數(shù)唯卖。

您也可以使用 COUNT(*) 結(jié)合 WHERE 子句來統(tǒng)計滿足特定條件的記錄數(shù)量粱玲,例如:

SELECT COUNT(*) AS passed_students
FROM students
WHERE score >= 60;

這將返回一個名為 "passed_students" 的結(jié)果集,其中包含了分?jǐn)?shù)大于等于 60 分的學(xué)生的記錄數(shù)量拜轨。

總之抽减,COUNT(*) 是 SQL 中非常常用的聚合函數(shù),用于統(tǒng)計行數(shù)橄碾,可以幫助您快速獲取所需信息的數(shù)量統(tǒng)計胯甩。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市堪嫂,隨后出現(xiàn)的幾起案子偎箫,更是在濱河造成了極大的恐慌,老刑警劉巖皆串,帶你破解...
    沈念sama閱讀 206,968評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件淹办,死亡現(xiàn)場離奇詭異,居然都是意外死亡恶复,警方通過查閱死者的電腦和手機怜森,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評論 2 382
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來谤牡,“玉大人副硅,你說我怎么就攤上這事〕嵊” “怎么了恐疲?”我有些...
    開封第一講書人閱讀 153,220評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我培己,道長碳蛋,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,416評論 1 279
  • 正文 為了忘掉前任省咨,我火速辦了婚禮肃弟,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘零蓉。我一直安慰自己笤受,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 64,425評論 5 374
  • 文/花漫 我一把揭開白布敌蜂。 她就那樣靜靜地躺著箩兽,像睡著了一般。 火紅的嫁衣襯著肌膚如雪紊册。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,144評論 1 285
  • 那天快耿,我揣著相機與錄音囊陡,去河邊找鬼。 笑死掀亥,一個胖子當(dāng)著我的面吹牛撞反,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播搪花,決...
    沈念sama閱讀 38,432評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼遏片,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了撮竿?” 一聲冷哼從身側(cè)響起吮便,我...
    開封第一講書人閱讀 37,088評論 0 261
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎幢踏,沒想到半個月后髓需,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,586評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡房蝉,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,028評論 2 325
  • 正文 我和宋清朗相戀三年僚匆,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片搭幻。...
    茶點故事閱讀 38,137評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡咧擂,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出檀蹋,到底是詐尸還是另有隱情松申,我是刑警寧澤,帶...
    沈念sama閱讀 33,783評論 4 324
  • 正文 年R本政府宣布,位于F島的核電站攻臀,受9級特大地震影響焕数,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜刨啸,卻給世界環(huán)境...
    茶點故事閱讀 39,343評論 3 307
  • 文/蒙蒙 一堡赔、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧设联,春花似錦善已、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,333評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至宫蛆,卻和暖如春艘包,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背耀盗。 一陣腳步聲響...
    開封第一講書人閱讀 31,559評論 1 262
  • 我被黑心中介騙來泰國打工想虎, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人叛拷。 一個月前我還...
    沈念sama閱讀 45,595評論 2 355
  • 正文 我出身青樓舌厨,卻偏偏與公主長得像,于是被迫代替她去往敵國和親忿薇。 傳聞我的和親對象是個殘疾皇子裙椭,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,901評論 2 345

推薦閱讀更多精彩內(nèi)容