成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

千萬(wàn)級(jí)的大表,如何做性能優(yōu)化?

數(shù)據(jù)庫(kù) 其他數(shù)據(jù)庫(kù)
很多小伙伴的數(shù)據(jù)庫(kù)在剛開始的時(shí)候表現(xiàn)良好,查詢也很流暢,但一旦表中的數(shù)據(jù)量上了千萬(wàn)級(jí),性能問題就開始浮現(xiàn):查詢慢、寫入卡、分頁(yè)拖沓、甚至偶爾直接宕機(jī)。

前言

大表優(yōu)化是一個(gè)老生常談的話題,但隨著業(yè)務(wù)規(guī)模的增長(zhǎng),總有人會(huì)“中招”。

很多小伙伴的數(shù)據(jù)庫(kù)在剛開始的時(shí)候表現(xiàn)良好,查詢也很流暢,但一旦表中的數(shù)據(jù)量上了千萬(wàn)級(jí),性能問題就開始浮現(xiàn):查詢慢、寫入卡、分頁(yè)拖沓、甚至偶爾直接宕機(jī)。

這時(shí)大家可能會(huì)想,是不是數(shù)據(jù)庫(kù)不行?是不是需要升級(jí)到更強(qiáng)的硬件?

其實(shí)很多情況下,根本問題在于沒做好優(yōu)化

今天,我們就從問題本質(zhì)講起,逐步分析大表常見的性能瓶頸,以及如何一步步優(yōu)化,希望對(duì)你會(huì)有所幫助。

1.為什么大表會(huì)慢?

在搞優(yōu)化之前,先搞清楚大表性能問題的根本原因。數(shù)據(jù)量大了,為什么數(shù)據(jù)庫(kù)就慢了?

1.1 磁盤IO瓶頸

大表的數(shù)據(jù)是存儲(chǔ)在磁盤上的,數(shù)據(jù)庫(kù)的查詢通常會(huì)涉及到數(shù)據(jù)塊的讀取。

當(dāng)數(shù)據(jù)量很大時(shí),單次查詢可能需要從多個(gè)磁盤塊中讀取大量數(shù)據(jù),磁盤的讀寫速度會(huì)直接限制查詢性能。

舉例:

假設(shè)有一張訂單表orders,里面存了5000萬(wàn)條數(shù)據(jù),你想要查詢某個(gè)用戶的最近10條訂單:

SELECT * FROM orders WHERE user_id = 123 ORDER BY order_time DESC LIMIT 10;

如果沒有索引,數(shù)據(jù)庫(kù)會(huì)掃描整個(gè)表的所有數(shù)據(jù),再進(jìn)行排序,性能肯定會(huì)拉胯。

1.2 索引失效或沒有索引

如果表的查詢沒有命中索引,數(shù)據(jù)庫(kù)會(huì)進(jìn)行全表掃描(Full Table Scan),也就是把表里的所有數(shù)據(jù)逐行讀一遍。

這種操作在千萬(wàn)級(jí)別的數(shù)據(jù)下非常消耗資源,性能會(huì)急劇下降。

舉例:

比如你在查詢時(shí)寫了這樣的條件:

SELECT * FROM orders WHERE DATE(order_time) = '2023-01-01';

這里用了DATE()函數(shù),數(shù)據(jù)庫(kù)需要對(duì)所有記錄的order_time字段進(jìn)行計(jì)算,導(dǎo)致索引失效。

1.3 分頁(yè)性能下降

分頁(yè)查詢是大表中很常見的場(chǎng)景,但深度分頁(yè)(比如第100頁(yè)之后)會(huì)導(dǎo)致性能問題。

即使你只需要10條數(shù)據(jù),但數(shù)據(jù)庫(kù)仍然需要先掃描出前面所有的記錄。

舉例:

查詢第1000頁(yè)的10條數(shù)據(jù):

SELECT * FROM orders ORDER BY order_time DESC LIMIT 9990, 10;

這條SQL實(shí)際上是讓數(shù)據(jù)庫(kù)先取出前9990條數(shù)據(jù),然后丟掉,再返回后面的10條。

隨著頁(yè)碼的增加,查詢的性能會(huì)越來越差。

1.4 鎖爭(zhēng)用

在高并發(fā)場(chǎng)景下,多個(gè)線程同時(shí)對(duì)同一張表進(jìn)行增刪改查操作,會(huì)導(dǎo)致行鎖或表鎖的爭(zhēng)用,進(jìn)而影響性能。

2.性能優(yōu)化的總體思路

性能優(yōu)化的本質(zhì)是減少不必要的IO、計(jì)算和鎖競(jìng)爭(zhēng),目標(biāo)是讓數(shù)據(jù)庫(kù)盡量少做“無用功”。

優(yōu)化的總體思路可以總結(jié)為以下幾點(diǎn):

  1. 表結(jié)構(gòu)設(shè)計(jì)要合理:盡量避免不必要的字段,數(shù)據(jù)能拆分則拆分。
  2. 索引要高效:設(shè)計(jì)合理的索引結(jié)構(gòu),避免索引失效。
  3. SQL要優(yōu)化:查詢條件精準(zhǔn),盡量減少全表掃描。
  4. 分庫(kù)分表:通過水平拆分、垂直拆分減少單表數(shù)據(jù)量。
  5. 緩存和異步化:減少對(duì)數(shù)據(jù)庫(kù)的直接壓力。

接下來,我們逐一展開。

3.表結(jié)構(gòu)設(shè)計(jì)優(yōu)化

表結(jié)構(gòu)是數(shù)據(jù)庫(kù)性能優(yōu)化的基礎(chǔ),設(shè)計(jì)不合理的表結(jié)構(gòu)會(huì)導(dǎo)致后續(xù)的查詢和存儲(chǔ)性能問題。

3.1 精簡(jiǎn)字段類型

字段的類型決定了存儲(chǔ)的大小和查詢的性能。

  • 能用INT的不要用BIGINT
  • 能用VARCHAR(100)的不要用TEXT
  • 時(shí)間字段建議用TIMESTAMPDATETIME,不要用CHARVARCHAR來存時(shí)間。

舉例:

-- 不推薦
CREATETABLE orders (
    idBIGINT,
    user_id BIGINT,
    order_status VARCHAR(255),
    remarks TEXT
);

-- 優(yōu)化后
CREATETABLE orders (
    idBIGINT,
    user_id INTUNSIGNED,
    order_status TINYINT, -- 狀態(tài)用枚舉表示
    remarks VARCHAR(500) -- 限制最大長(zhǎng)度
);

這樣可以節(jié)省存儲(chǔ)空間,查詢時(shí)也更高效。

如果對(duì)表設(shè)計(jì)比較感興趣,可以看看我之前的另一篇文章《表設(shè)計(jì)的18條軍規(guī)》,里面有詳細(xì)的介紹。

3.2  表拆分:垂直拆分與水平拆分

垂直拆分

當(dāng)表中字段過多,某些字段并不是經(jīng)常查詢的,可以將表按照業(yè)務(wù)邏輯拆分為多個(gè)小表。

示例: 將訂單表分為兩個(gè)表:orders_basic 和 orders_details

-- 基本信息表
CREATETABLE orders_basic (
    idBIGINT PRIMARY KEY,
    user_id INTUNSIGNED,
    order_time TIMESTAMP
);

-- 詳情表
CREATETABLE orders_details (
    idBIGINT PRIMARY KEY,
    remarks VARCHAR(500),
    shipping_address VARCHAR(255)
);

水平拆分

當(dāng)單表的數(shù)據(jù)量過大時(shí),可以按一定規(guī)則拆分到多張表中。

示例: 假設(shè)我們按用戶ID對(duì)訂單表進(jìn)行水平拆分:

orders_0 -- 存user_id % 2 = 0的訂單
orders_1 -- 存user_id % 2 = 1的訂單

拆分后每張表的數(shù)據(jù)量大幅減少,查詢性能會(huì)顯著提升。

4.索引優(yōu)化

索引是數(shù)據(jù)庫(kù)性能優(yōu)化的“第一殺器”,但很多人對(duì)索引的使用并不熟悉,導(dǎo)致性能不升反降。

4.1  創(chuàng)建合適的索引

為高頻查詢的字段創(chuàng)建索引,比如主鍵、外鍵、查詢條件字段。

示例:

CREATE INDEX idx_user_id_order_time ON orders (user_id, order_time DESC);

上面的復(fù)合索引可以同時(shí)加速user_idorder_time的查詢。

4.2  避免索引失效

  • 別對(duì)索引字段使用函數(shù)或運(yùn)算。錯(cuò)誤:
SELECT * FROM orders WHERE DATE(order_time) = '2023-01-01';

優(yōu)化:

SELECT * FROM orders WHERE order_time >= '2023-01-01 00:00:00'
  AND order_time < '2023-01-02 00:00:00';
  • 注意隱式類型轉(zhuǎn)換。錯(cuò)誤:
SELECT * FROM orders WHERE user_id = '123';

優(yōu)化:

SELECT * FROM orders WHERE user_id = 123;

如果對(duì)索引失效問題比較感興趣,可以看看我之前的另一篇文章《聊聊索引失效的10種場(chǎng)景,太坑了》,里面有詳細(xì)的介紹。

5.SQL優(yōu)化

5.1 減少查詢字段

只查詢需要的字段,避免SELECT *

-- 錯(cuò)誤
SELECT * FROM orders WHERE user_id = 123;

-- 優(yōu)化
SELECT id, order_time FROM orders WHERE user_id = 123;

5.2 分頁(yè)優(yōu)化

深度分頁(yè)時(shí),使用“延遲游標(biāo)”的方式避免掃描過多數(shù)據(jù)。

-- 深分頁(yè)(性能較差)
SELECT * FROM orders ORDER BY order_time DESC LIMIT 9990, 10;

-- 優(yōu)化:使用游標(biāo)
SELECT * FROM orders WHERE order_time < '2023-01-01 12:00:00'
  ORDER BY order_time DESC LIMIT 10;

如果對(duì)SQL優(yōu)化比較感興趣,可以看看我之前的另一篇文章《聊聊sql優(yōu)化的15個(gè)小技巧》,里面有詳細(xì)的介紹。

6.分庫(kù)分表

6.1 水平分庫(kù)分表

當(dāng)單表拆分后仍無法滿足性能需求,可以通過分庫(kù)分表將數(shù)據(jù)分散到多個(gè)數(shù)據(jù)庫(kù)中。

常見的分庫(kù)分表規(guī)則:

  • 按用戶ID取模。
  • 按時(shí)間分區(qū)。

如果對(duì)分庫(kù)分表比較感興趣,可以看看我之前的另一篇文章《阿里二面:為什么要分庫(kù)分表?》,里面有詳細(xì)的介紹。

7.緩存與異步化

7.1 使用Redis緩存熱點(diǎn)數(shù)據(jù)

對(duì)高頻查詢的數(shù)據(jù)可以存儲(chǔ)到Redis中,減少對(duì)數(shù)據(jù)庫(kù)的直接訪問。

示例:

// 從緩存讀取數(shù)據(jù)
String result = redis.get("orders:user:123");
if (result == null) {
    result = database.query("SELECT * FROM orders WHERE user_id = 123");
    redis.set("orders:user:123", result, 3600); // 設(shè)置緩存1小時(shí)
}

7.2 使用消息隊(duì)列異步處理寫操作

高并發(fā)寫入時(shí),可以將寫操作放入消息隊(duì)列(如Kafka),然后異步批量寫入數(shù)據(jù)庫(kù),減輕數(shù)據(jù)庫(kù)壓力。

如果對(duì)Kafka的一些問題比較感興趣,可以看看我之前的另一篇文章《我用kafka兩年踩過的一些非比尋常的坑》,里面有詳細(xì)的介紹。

8.實(shí)戰(zhàn)案例

問題:

某電商系統(tǒng)的訂單表存儲(chǔ)了5000萬(wàn)條記錄,用戶查詢訂單詳情時(shí),頁(yè)面加載時(shí)間超過10秒。

解決方案:

  1. 垂直拆分訂單表:將訂單詳情字段拆分到另一個(gè)表中。
  2. 創(chuàng)建復(fù)合索引:為user_idorder_time創(chuàng)建索引。
  3. 使用Redis緩存:將最近30天的訂單緩存到Redis中。
  4. 分頁(yè)優(yōu)化:使用search_after代替LIMIT深分頁(yè)。

總結(jié)

大表性能優(yōu)化是一個(gè)系統(tǒng)性工程,需要從表結(jié)構(gòu)、索引、SQL到架構(gòu)設(shè)計(jì)全方位考慮。

千萬(wàn)級(jí)別的數(shù)據(jù)量看似龐大,但通過合理的拆分、索引設(shè)計(jì)和緩存策略,可以讓數(shù)據(jù)庫(kù)輕松應(yīng)對(duì)。

責(zé)任編輯:武曉燕 來源: 蘇三說技術(shù)
相關(guān)推薦

2022-08-03 09:11:31

React性能優(yōu)化

2023-12-29 08:29:15

QPS系統(tǒng)應(yīng)用

2011-03-01 10:42:23

無線局域網(wǎng)局域網(wǎng)性能優(yōu)化

2024-11-05 11:14:05

2012-05-07 08:49:57

Clojure

2018-07-26 14:50:00

數(shù)據(jù)庫(kù)MySQL大表優(yōu)化

2020-02-05 14:49:04

網(wǎng)絡(luò)性能優(yōu)化微調(diào)

2018-12-17 09:02:25

百億大表維度查詢

2024-06-19 09:38:05

2020-02-11 08:02:26

千萬(wàn)級(jí)大表優(yōu)化

2019-01-17 10:58:37

2022-07-25 08:02:57

Tomcat調(diào)優(yōu)組件

2013-08-26 15:09:23

互聯(lián)網(wǎng)測(cè)試

2015-09-08 14:42:17

Android性能優(yōu)化

2019-11-19 07:56:30

MySQL壓測(cè)數(shù)據(jù)表

2021-07-30 05:05:32

場(chǎng)景

2012-03-12 16:42:54

測(cè)試

2015-07-30 11:21:16

代碼審查

2020-12-18 10:40:00

ExcelJava代碼

2020-08-06 08:00:51

數(shù)據(jù)分頁(yè)優(yōu)化
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 日韩精品一区二区三区 | 操人网| 91久久| 老司机精品福利视频 | 成人国产在线视频 | 国产精品美女久久久 | 国产精品99久久久久久久久久久久 | 精品国产一区二区三区免费 | 亚洲国产精品精华素 | 久久综合欧美 | www免费视频 | 成人欧美一区二区三区黑人孕妇 | 国产伦精品一区二区三区在线 | 亚洲精品国产成人 | 欧美专区在线 | 午夜一级做a爰片久久毛片 精品综合 | 亚洲美女网站 | 91在线视频观看免费 | 欧美日韩不卡合集视频 | 亚洲在线一区二区 | 瑟瑟激情 | 亚洲精品一区二区三区在线 | www国产成人| 欧美精品 在线观看 | 99爱在线| 国产精品久久久久一区二区 | 久久久久精| 97偷拍视频 | 亚洲一区二区三区高清 | 91福利在线观看 | 99精品一区二区三区 | 成人免费看电影 | 羞羞羞视频 | 久久久久91| 欧美精品三区 | 九九在线精品视频 | 国产99久久久国产精品 | 免费观看一级特黄欧美大片 | 麻豆av在线 | 91在线电影 | 国产精品久久久久久二区 |