0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

數(shù)據(jù)庫(kù)優(yōu)化那些事

科技綠洲 ? 來(lái)源:Java技術(shù)指北 ? 作者:Java技術(shù)指北 ? 2023-10-08 11:49 ? 次閱讀

我們出去面試經(jīng)常會(huì)被問(wèn)到數(shù)據(jù)庫(kù)這一塊,而涉及數(shù)據(jù)庫(kù)這一塊問(wèn)的最多的就是數(shù)據(jù)庫(kù)優(yōu)化。那么我們?cè)趺醋霾拍茏龊脙?yōu)化問(wèn)題呢?今天我們就來(lái)聊聊數(shù)據(jù)庫(kù)優(yōu)化那些事。

數(shù)據(jù)庫(kù)優(yōu)化我們一般可以從以下幾個(gè)方面考慮:

  • 數(shù)據(jù)庫(kù)
  • 表設(shè)計(jì)
  • sql語(yǔ)句優(yōu)化

數(shù)據(jù)庫(kù)

大型項(xiàng)目拆分為小項(xiàng)目,每個(gè)項(xiàng)目有自己獨(dú)立的數(shù)據(jù)庫(kù)

原來(lái)所有數(shù)據(jù)表都放在一個(gè)數(shù)據(jù)庫(kù)節(jié)點(diǎn)上,所有的讀寫請(qǐng)求也都發(fā)到這個(gè)MySQL上面,所以數(shù)據(jù)庫(kù)的負(fù)載太高。如果把一個(gè)節(jié)點(diǎn)的數(shù)據(jù)庫(kù)拆分成多個(gè)MySQL數(shù)據(jù)庫(kù),這樣就可以有效的降低每個(gè)MySQL數(shù)據(jù)庫(kù)的負(fù)載。

分表分庫(kù)(取模分表、水平分表、垂直分表)

通過(guò)取模算法進(jìn)行水平分表,例如總共有3張表, 1%3=1 放入第一張表,2%3=2,放入低二張表,3%3=0 放入第0張表,相當(dāng)于用幾張表來(lái)平分一張表,最好的做法是一張主表,再來(lái)幾張字表。因?yàn)榉直聿缓米龇猪?yè),數(shù)據(jù)存放在多張表中,所以需要一張主表用來(lái)存放所有的數(shù)據(jù),當(dāng)子表無(wú)法滿足時(shí)采用主表。

讀寫分離

把對(duì)數(shù)據(jù)庫(kù)的讀寫操作分到不同的數(shù)據(jù)庫(kù)服務(wù)上,以實(shí)現(xiàn)數(shù)據(jù)庫(kù)的高性能和高并發(fā)能力;讀寫分離最大的弊端就是復(fù)制延遲,對(duì)于以查詢?yōu)橹鞯捻?xiàng)目比較合適,看項(xiàng)目進(jìn)行取舍。

表設(shè)計(jì)

數(shù)據(jù)庫(kù)表設(shè)計(jì)遵循三范式

  1. 第一范式:原子約束,每列不能再分

圖片

  1. 第二范式:每張表只描述一件事情,就是主鍵就對(duì)應(yīng)著所有信息。
  2. 第三范式:要保證表中的數(shù)據(jù)和主鍵直接相關(guān),而不是間接相關(guān)。
    比如訂單表中出現(xiàn)了快遞的屬性(快遞單號(hào),收件人姓名、收貨地址),可以把收件人姓名和收貨地址提出來(lái)單獨(dú)放到一張表,只留快遞單號(hào)在訂單表中作為關(guān)聯(lián)。并不是所有的表設(shè)計(jì)都必須按照三大范式設(shè)計(jì),具體需要根據(jù)需求來(lái)定

表字段設(shè)計(jì)

盡量設(shè)計(jì)成not null,盡量使用數(shù)字型字段(如性別,男:1 女:2),若只含數(shù)值信息的字段盡量不要設(shè)計(jì)為字符型,這會(huì)降低查詢和連接的性能,并會(huì)增加存儲(chǔ)開(kāi)銷,字段長(zhǎng)度設(shè)計(jì)合理,比如郵編,只需要位長(zhǎng)度,沒(méi)必要過(guò)長(zhǎng),

用varchar/nvarchar 代替 char/nchar

因?yàn)槭紫茸冮L(zhǎng)字段存儲(chǔ)空間小,可以節(jié)省存儲(chǔ)空間,其次對(duì)于查詢來(lái)說(shuō),在一個(gè)相對(duì)較小的字段內(nèi)搜索效率顯然要高些。不要以為 NULL 不需要空間,比如:char(100) 型,在字段建立時(shí),空間就固定了, 不管是否插入值(NULL也包含在內(nèi)),都是占用 100個(gè)字符的空間的,如果是varchar這樣的變長(zhǎng)字段, null 不占用空間。

sql語(yǔ)句優(yōu)化

  • 最大化使用索引,合理的創(chuàng)建索引情況下,最大化使用索引
  • 減少數(shù)據(jù)訪問(wèn):設(shè)置合理的字段類型
  • 返回更少的數(shù)據(jù):只返回需要的字段和數(shù)據(jù)分頁(yè)處理
  • 減少交互次數(shù):批量DML操作,函數(shù)存儲(chǔ)等減少數(shù)據(jù)連接次數(shù)
  • 盡量減少數(shù)據(jù)庫(kù)排序操作以及全表查詢
    sql語(yǔ)句優(yōu)化的時(shí)候首先,我們需要定位有沒(méi)有慢查詢 慢查詢 ,顧名思義,執(zhí)行很慢的查詢。有多慢?超過(guò)long_query_time參數(shù)設(shè)定的時(shí)間閾值(默認(rèn)10s)

    慢查詢基本配置

  • slow_query_log 啟動(dòng)停止技術(shù)慢查詢?nèi)罩?/li>
  • slow_query_log_file 指定慢查詢?nèi)罩镜么鎯?chǔ)路徑及文件(默認(rèn)和數(shù)據(jù)文件放一起)
  • long_query_time 指定記錄慢查詢?nèi)罩維QL執(zhí)行時(shí)間得伐值(單位:秒,默認(rèn)10秒)
  • log_queries_not_using_indexes 是否記錄未使用索引的SQL
  • log_output 日志存放的地方【TABLE】【FILE】【FILE,TABLE】

mysql5.7以上的版本,在my.ini中配置慢查詢配置

# 啟動(dòng)慢查詢?nèi)罩?/span>
slow_query_log = ON
# 慢查詢?nèi)罩敬娣诺胤?/span>
slow_query_log_file = D:softwaremysqlmysql-5.7.24-winx64datalogsshow.log
# 設(shè)置慢查詢時(shí)間,默認(rèn)10秒,我們此處設(shè)置為1秒,也就是超過(guò)1秒就是慢查詢
long_query_time = 1

通過(guò)下面命令查看下上面的配置:

  • show VARIABLES like '%slow_query_log%'
  • show VARIABLES like '%slow_query_log_file%'
  • show VARIABLES like '%long_query_time%'
  • show VARIABLES like '%log_queries_not_using_indexes%'
  • show VARIABLES like 'log_output'
  • set global long_query_time=1; -- 默認(rèn)10秒,這里為了演示方便設(shè)置為1
  • set GLOBAL slow_query_log = 1; -- 開(kāi)啟慢查詢?nèi)罩?/li>
  • set global log_output='FILE' -- 項(xiàng)目開(kāi)發(fā)中日志只能記錄在日志文件中,不能記表中

例如現(xiàn)在我執(zhí)行 select sleep(2) 沉睡兩秒,超過(guò)我設(shè)置慢查詢時(shí)間1秒,就會(huì)會(huì)被記錄到慢查詢?nèi)罩局腥缦?/p>

圖片有查詢時(shí)間,以及慢查詢語(yǔ)句,當(dāng)我們知道慢查詢語(yǔ)句了我們就可以針對(duì)性優(yōu)化sql了。而針對(duì)sql的優(yōu)化最多的就是添加索引

索引

索引用來(lái)快速地尋找那些具有特定值的記錄,所有MySQL索引都以B-樹(shù)的形式保存。如果沒(méi)有索引,執(zhí)行查詢時(shí)MySQL必須從第一個(gè)記錄開(kāi)始掃描整個(gè)表的所有記錄,直至找到符合要求的記錄。表里面的記錄數(shù)量越多,這個(gè)操作的代價(jià)就越高。如果作為搜索條件的列上已經(jīng)創(chuàng)建了索引,MySQL無(wú)需掃描任何記錄即可迅速得到目標(biāo)記錄所在的位置。

索引原理 :折半查找,減少全表掃描,索引文件中是一個(gè)B_tree ,索引的最大查找數(shù)為2^n次方,查找數(shù)獨(dú)比較快

我們可以使用explain分析SQL的執(zhí)行計(jì)劃。該執(zhí)行計(jì)劃可以模擬SQL優(yōu)化器執(zhí)行SQL語(yǔ)句,可以幫助我們了解到自己編寫SQL是否有用到索引。1)查看執(zhí)行計(jì)劃 語(yǔ)法:explain + SQL語(yǔ)句 eg:explain select * from tb;

圖片

id :編號(hào)
select_type :查詢類型
table :表
type :類型
possible_keys :預(yù)測(cè)用到的索引
key :實(shí)際使用的索引
key_len :實(shí)際使用索引的長(zhǎng)度
ref :表之間的引用
rows :通過(guò)索引查詢到的數(shù)據(jù)量
Extra :額外的信息

創(chuàng)建索引 create index index_name on table_name(colum_name...);

索引使用注意事項(xiàng)

  1. 索引加在常使用字段上,主鍵除外,主鍵自帶唯一索引,例如商品表查詢名字和價(jià)格比較多的情況,就在這兩個(gè)字段上加索引
  2. 盡量避免使用子查詢,用關(guān)聯(lián)查詢替代
select t1.name,(select sex from user u1 where u1.user_id = t1.user_id) as sex from userInfo t1 
改成
select t1.name,u1.sex from userInfo left join user u1 on u1.user_id = t1.user_id;
  1. 用in來(lái)替換or ,且含In的范圍查詢,放到where條件的最后,防止索引失效。select * from ep_product where channel_id = 1 or channel_id = 2 改成 select * from ep_product where channel_id in(1,2)
  2. 盡量不要使用or,否則索引失效圖片
  3. 不要使用like "%%",會(huì)全表掃描,但是可以使用 like "_%",不以%開(kāi)頭,會(huì)使用到索引進(jìn)行查找 使用"%%"

圖片使用"_%"

圖片

  1. 判斷是否為null不能用=,要用is null ,=null 不會(huì)使用索引,is null會(huì)使用索引

圖片

圖片

  1. 避免數(shù)據(jù)類型不一致,如果設(shè)置的是int類型,條件最好是傳入int類型,如果傳入String類型數(shù)據(jù)庫(kù)會(huì)先做轉(zhuǎn)換在執(zhí)行sql
select * from product where id = "1"
select * from product where id = 1
  1. 最好不要給數(shù)據(jù)庫(kù)留 NULL,盡可能的使用 NOT NULL 填充數(shù)據(jù)庫(kù),可以在 name 上設(shè)置默認(rèn)值 0,確保表中 name 列沒(méi)有 null 值,然后這樣查詢:
select id from t where name = 0
  1. 分組的時(shí)候需要效率比較高就禁止使用排序、在group by 后面加上order by null
select channel_id,count(*) from ep_product  GROUP BY channel_id 
改成
select channel_id,count(*) from ep_product  GROUP BY channel_id order by null
  1. 應(yīng)盡量避免在 where 子句中對(duì)字段進(jìn)行表達(dá)式操作,這將導(dǎo)致引擎放棄使用索引而進(jìn)行全表掃描。
select * from product where sell_price/2 = 100
改成 
select * from product where sell_price = 100*2
  1. 在使用索引字段作為條件時(shí),如果該索引是復(fù)合索引,那么必須使用到該索引中的第一個(gè)字段作為條件時(shí)才能保證系統(tǒng)使用該索引,否則該索引將不會(huì)被使用,并且應(yīng)盡可能的讓字段順序與索引順序相一致。
  • 復(fù)合索引,不要跨列或無(wú)序使用(左匹配原則)
  • 復(fù)合索引,盡量使用全索引匹配,也就是說(shuō),你建立幾個(gè)索引,就使用幾個(gè)索引
  1. Update 語(yǔ)句,如果只更改1、2個(gè)字段,不要Update全部字段,否則頻繁調(diào)用會(huì)引起明顯的性能消耗,同時(shí)帶來(lái)大量日志
  2. 左關(guān)聯(lián)查詢,左表加索引,有關(guān)聯(lián)查詢,右表加索引
  3. 索引并不是越多越好,索引固然可以提高相應(yīng)的 select 的效率,但同時(shí)也降低了 insert 及 update 的效率,因?yàn)?insert 或 update 時(shí)有可能會(huì)重建索引,所以怎樣建索引需要慎重考慮,視具體情況而定。

其他注意事項(xiàng)

  1. 避免出現(xiàn)select *
  2. 關(guān)聯(lián)查詢的表最好不超過(guò)3張,數(shù)據(jù)庫(kù)的性能更加重要,適當(dāng)考慮規(guī)范性就好
  3. 多表關(guān)聯(lián)查詢時(shí),小表在前,大表在后。
  4. 新增多條數(shù)據(jù)是避免使用
insert into user values(1,"張三");
  insert into user values(2,"李四");
  使用以下方式可以減少語(yǔ)句解析的操作
  insert into user values(1,"張三"),(2,"李四");
聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 數(shù)據(jù)庫(kù)
    +關(guān)注

    關(guān)注

    7

    文章

    3733

    瀏覽量

    64169
  • 函數(shù)
    +關(guān)注

    關(guān)注

    3

    文章

    4256

    瀏覽量

    62223
  • MySQL
    +關(guān)注

    關(guān)注

    1

    文章

    790

    瀏覽量

    26351
  • 日志
    +關(guān)注

    關(guān)注

    0

    文章

    131

    瀏覽量

    10615
收藏 人收藏

    評(píng)論

    相關(guān)推薦

    數(shù)據(jù)庫(kù)SQL的優(yōu)化

    數(shù)據(jù)庫(kù)執(zhí)行SQL都會(huì)先進(jìn)行語(yǔ)義解析,然后將SQL分成一步一步可執(zhí)行的計(jì)劃,然后逐步執(zhí)行。通過(guò)分析執(zhí)行計(jì)劃,我們可以清晰的看到數(shù)據(jù)庫(kù)執(zhí)行的操作,這對(duì)于數(shù)據(jù)庫(kù)SQL的優(yōu)化具有重大意義。 1
    的頭像 發(fā)表于 10-09 15:43 ?984次閱讀
    <b class='flag-5'>數(shù)據(jù)庫(kù)</b>SQL的<b class='flag-5'>優(yōu)化</b>

    數(shù)據(jù)庫(kù)設(shè)計(jì)及開(kāi)發(fā)規(guī)范之sql性能優(yōu)化

    數(shù)據(jù)庫(kù)設(shè)計(jì)及開(kāi)發(fā)規(guī)范,sql性能優(yōu)化
    發(fā)表于 05-08 10:58

    基于數(shù)據(jù)庫(kù)查詢過(guò)程優(yōu)化設(shè)計(jì)

    在大型關(guān)系數(shù)據(jù)庫(kù)管理與開(kāi)發(fā)中,優(yōu)化設(shè)計(jì)極大地提高數(shù)據(jù)庫(kù)的性能。通過(guò)對(duì)一大型數(shù)據(jù)庫(kù)查詢語(yǔ)句執(zhí)行過(guò)程的討論,提出了對(duì)同一表格進(jìn)行多個(gè)選擇運(yùn)算的優(yōu)化
    發(fā)表于 02-27 16:05 ?18次下載

    數(shù)據(jù)庫(kù)開(kāi)發(fā)這點(diǎn)

    數(shù)據(jù)庫(kù)開(kāi)發(fā)這點(diǎn)
    發(fā)表于 11-06 10:03 ?0次下載

    如何優(yōu)化數(shù)據(jù)庫(kù)負(fù)載

    摘要:一個(gè)前端開(kāi)發(fā)者介紹了他和他的數(shù)據(jù)庫(kù)朋友們是如何降低基于Ruby網(wǎng)站數(shù)據(jù)庫(kù)負(fù)載的故事。以下為譯文: 數(shù)據(jù)庫(kù)負(fù)載可能是個(gè)沉默的性能殺手。我一直都在優(yōu)化我的一個(gè)網(wǎng)站應(yīng)用,用來(lái)吸引人們參
    發(fā)表于 09-28 16:32 ?0次下載

    提高Oracle的數(shù)據(jù)庫(kù)性能

    問(wèn)題。通過(guò)優(yōu)化SQL語(yǔ)句效率、擴(kuò)充高級(jí)緩沖區(qū)和配置重做日志緩沖區(qū)等幾個(gè)方面介紹了Oracle數(shù)據(jù)庫(kù)優(yōu)化方法,探討了OraCle如何提高性能優(yōu)化的措施。通過(guò)測(cè)試Oracle查詢結(jié)果表明,
    發(fā)表于 11-11 18:16 ?4次下載

    醫(yī)院SQL數(shù)據(jù)庫(kù)系統(tǒng)語(yǔ)句優(yōu)化

    本文就如何優(yōu)化大型數(shù)據(jù)庫(kù)的性能進(jìn)行了一些探索,提出了優(yōu)化數(shù)據(jù)庫(kù)訪問(wèn)性能的若干策略,特別是對(duì)SQL語(yǔ)句進(jìn)行了有效的分析設(shè)計(jì)的問(wèn)題,以使其加快執(zhí)行速度,減少網(wǎng)絡(luò)傳輸,能更高效地工作,充分發(fā)
    的頭像 發(fā)表于 02-17 20:26 ?5262次閱讀

    基于Greenplum數(shù)據(jù)庫(kù)的查詢優(yōu)化

    針對(duì)分布式數(shù)據(jù)庫(kù)查詢效率隨著數(shù)據(jù)規(guī)模的增大而降低的問(wèn)題,以Greenplum分布式數(shù)據(jù)庫(kù)為研究對(duì)象,從優(yōu)化查詢路徑的角度提出一個(gè)基于代價(jià)的最優(yōu)查詢計(jì)劃生成方法。首先,該方法設(shè)計(jì)一種有效
    發(fā)表于 03-29 17:46 ?0次下載

    數(shù)據(jù)庫(kù)教程之如何進(jìn)行數(shù)據(jù)庫(kù)設(shè)計(jì)

    本文檔的主要內(nèi)容詳細(xì)介紹的是數(shù)據(jù)庫(kù)教程之如何進(jìn)行數(shù)據(jù)庫(kù)設(shè)計(jì)內(nèi)容包括了:1 數(shù)據(jù)庫(kù)設(shè)計(jì)概述 ,2 數(shù)據(jù)庫(kù)需求分析 ,3 數(shù)據(jù)庫(kù)結(jié)構(gòu)設(shè)計(jì) ,4
    發(fā)表于 10-19 10:41 ?21次下載
    <b class='flag-5'>數(shù)據(jù)庫(kù)</b>教程之如何進(jìn)行<b class='flag-5'>數(shù)據(jù)庫(kù)</b>設(shè)計(jì)

    數(shù)據(jù)庫(kù)系統(tǒng)概論之如何進(jìn)行關(guān)系查詢處理和查詢優(yōu)化

    本文檔的主要內(nèi)容詳細(xì)介紹的是數(shù)據(jù)庫(kù)系統(tǒng)概論之如何進(jìn)行關(guān)系查詢處理和查詢優(yōu)化主要內(nèi)容包括了:1、關(guān)系數(shù)據(jù)庫(kù)系統(tǒng)的查詢處理 2、關(guān)系數(shù)據(jù)庫(kù)系統(tǒng)的查詢優(yōu)化
    發(fā)表于 11-15 15:12 ?11次下載
    <b class='flag-5'>數(shù)據(jù)庫(kù)</b>系統(tǒng)概論之如何進(jìn)行關(guān)系查詢處理和查詢<b class='flag-5'>優(yōu)化</b>

    數(shù)據(jù)庫(kù)和自建數(shù)據(jù)庫(kù)的區(qū)別及應(yīng)用

    數(shù)據(jù)庫(kù)是指優(yōu)化和部署在云端的數(shù)據(jù)庫(kù),阿里云和騰訊云都提供云數(shù)據(jù)庫(kù),云數(shù)據(jù)庫(kù)和自己搭建的數(shù)據(jù)庫(kù)
    的頭像 發(fā)表于 11-20 16:26 ?4518次閱讀
    云<b class='flag-5'>數(shù)據(jù)庫(kù)</b>和自建<b class='flag-5'>數(shù)據(jù)庫(kù)</b>的區(qū)別及應(yīng)用

    數(shù)據(jù)庫(kù)索引使用策略及優(yōu)化

    的內(nèi)容完全基于上文的理論基礎(chǔ),實(shí)際上一旦理解了索引背后的機(jī)制,那么選擇高性能的策略就變成了純粹的推理,并且可以理解這些策略背后的邏輯。 示例數(shù)據(jù)庫(kù) 為了討論索引策略,需要一個(gè)數(shù)據(jù)量不算小的數(shù)據(jù)庫(kù)作為示例。本文選用MySQL官方文
    的頭像 發(fā)表于 11-02 15:13 ?1641次閱讀
    <b class='flag-5'>數(shù)據(jù)庫(kù)</b>索引使用策略及<b class='flag-5'>優(yōu)化</b>

    MySQL數(shù)據(jù)庫(kù)性能優(yōu)化的意義及其措施

    數(shù)據(jù)庫(kù)性能優(yōu)化的常見(jiàn)手段有很多,比如添加索引、分庫(kù)分表、優(yōu)化連接池等
    的頭像 發(fā)表于 02-03 14:12 ?1186次閱讀

    數(shù)據(jù)庫(kù)優(yōu)化最有效的方式是什么?

    隨著業(yè)務(wù)數(shù)據(jù)量和網(wǎng)站QPS日益增高,對(duì)數(shù)據(jù)庫(kù)壓力也越來(lái)越大,單機(jī)版數(shù)據(jù)庫(kù)很快會(huì)到達(dá)存儲(chǔ)和并發(fā)瓶頸,就需要做數(shù)據(jù)庫(kù)性能方面的優(yōu)化,分庫(kù)分表采取
    的頭像 發(fā)表于 02-28 09:46 ?644次閱讀

    python讀取數(shù)據(jù)庫(kù)數(shù)據(jù) python查詢數(shù)據(jù)庫(kù) python數(shù)據(jù)庫(kù)連接

    python讀取數(shù)據(jù)庫(kù)數(shù)據(jù) python查詢數(shù)據(jù)庫(kù) python數(shù)據(jù)庫(kù)連接 Python是一門高級(jí)編程語(yǔ)言,廣泛應(yīng)用于各種領(lǐng)域。其中,Python在
    的頭像 發(fā)表于 08-28 17:09 ?1683次閱讀