最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

一文詳解MySQL實(shí)現(xiàn)分庫分表的詳細(xì)步驟

 更新時(shí)間:2025年12月26日 14:43:05   作者:悟空碼字  
在MySQL數(shù)據(jù)庫的使用過程中,當(dāng)數(shù)據(jù)量增長到一定規(guī)模時(shí),單庫單表的架構(gòu)會(huì)面臨性能瓶頸,此時(shí)就需要考慮分庫分表,下面我們就來看看分庫分表的具體實(shí)現(xiàn)方法吧

一、分庫分表是什么?——數(shù)據(jù)庫的“甜蜜煩惱”

把你的MySQL數(shù)據(jù)庫想象成是個(gè)小單身公寓(單庫單表):

  • 剛開始住進(jìn)去時(shí),東西不多,找啥都方便
  • 后來你結(jié)婚了(用戶量增加),生了娃(數(shù)據(jù)量暴增),還養(yǎng)了條二哈(業(yè)務(wù)復(fù)雜了)
  • 現(xiàn)在全家擠在小公寓里,每天早上一家人搶廁所(數(shù)據(jù)庫鎖競爭),找雙襪子要翻遍全家(全表掃描)
  • 鄰居天天投訴你家太吵(性能影響其他服務(wù))

這時(shí)候你需要: 分庫:買下整棟樓!把不同的家人安排在不同樓層(業(yè)務(wù)垂直拆分) 分表:把每個(gè)房間再隔成小隔間!把襪子、內(nèi)褲、外套分開放(數(shù)據(jù)水平拆分)

二、詳細(xì)實(shí)施步驟——從“蝸居”到“豪宅”的裝修指南

第1步:設(shè)計(jì)藍(lán)圖——想清楚再動(dòng)手

-- 先看看現(xiàn)在的“房子”有多大
SELECT 
    TABLE_SCHEMA as '數(shù)據(jù)庫',
    TABLE_NAME as '表名',
    ROUND((DATA_LENGTH + INDEX_LENGTH) / 1024 / 1024, 2) as '大小(MB)',
    TABLE_ROWS as '行數(shù)'
FROM information_schema.TABLES 
WHERE TABLE_SCHEMA = '你的數(shù)據(jù)庫名'
ORDER BY (DATA_LENGTH + INDEX_LENGTH) DESC;

-- 思考人生三連問:
-- 1. 按業(yè)務(wù)分?(用戶相關(guān)、訂單相關(guān)、商品相關(guān))
-- 2. 按時(shí)間分?(2024訂單、2025訂單)
-- 3. 按地域分?(北京用戶、上海用戶)

第2步:垂直分庫——讓專業(yè)的人住專業(yè)的樓層

-- 原來都擠在一個(gè)庫里
CREATE DATABASE single_apartment;

-- 現(xiàn)在買棟樓,每層一個(gè)專業(yè)戶
CREATE DATABASE user_villa;      -- 用戶專屬樓層
CREATE DATABASE order_mansion;   -- 訂單豪華層
CREATE DATABASE product_tower;   -- 商品展示層

-- 用戶表搬到用戶樓層
CREATE TABLE user_villa.user_info (
    user_id BIGINT PRIMARY KEY AUTO_INCREMENT,
    username VARCHAR(50) NOT NULL,
    email VARCHAR(100),
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
    -- 用戶相關(guān)的其他字段...
);

-- 訂單表搬到訂單樓層  
CREATE TABLE order_mansion.order_info (
    order_id BIGINT PRIMARY KEY AUTO_INCREMENT,
    user_id BIGINT NOT NULL,
    amount DECIMAL(10, 2),
    status TINYINT,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
    -- 訂單相關(guān)的其他字段...
);

第3步:水平分表——每個(gè)房間都裝上帝視角衣柜

方法一:按范圍分表(適合時(shí)間序列)

-- 訂單表按月份拆分,再也不怕找去年的訂單像考古了
-- 2024年訂單表
CREATE TABLE order_mansion.order_202401 (
    order_id BIGINT PRIMARY KEY AUTO_INCREMENT,
    user_id BIGINT NOT NULL,
    -- ... 其他字段
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    INDEX idx_user_id (user_id),
    INDEX idx_created_at (created_at)
) PARTITION BY RANGE (MONTH(created_at)) (
    PARTITION p1 VALUES LESS THAN (2),
    PARTITION p2 VALUES LESS THAN (3),
    -- ... 更多分區(qū)
);

-- 2024年2月訂單表
CREATE TABLE order_mansion.order_202402 (
    -- 結(jié)構(gòu)同上
);

方法二:按哈希分表(均勻分布)

-- 用戶表按ID取模分表,16張表夠不夠?
-- 先創(chuàng)建用戶表模板
DELIMITER $$

CREATE PROCEDURE create_user_tables()
BEGIN
    DECLARE i INT DEFAULT 0;
    WHILE i < 16 DO
        SET @table_name = CONCAT('user_villa.user_info_', LPAD(i, 2, '0'));
        SET @sql = CONCAT('
            CREATE TABLE IF NOT EXISTS ', @table_name, ' (
                user_id BIGINT PRIMARY KEY AUTO_INCREMENT,
                username VARCHAR(50) NOT NULL,
                email VARCHAR(100),
                created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
                INDEX idx_username (username)
            ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
        ');
        PREPARE stmt FROM @sql;
        EXECUTE stmt;
        DEALLOCATE PREPARE stmt;
        SET i = i + 1;
    END WHILE;
END$$

DELIMITER ;

-- 執(zhí)行創(chuàng)建
CALL create_user_tables();

第4步:路由策略——給每個(gè)數(shù)據(jù)配個(gè)“導(dǎo)航系統(tǒng)”

// Java代碼示例:數(shù)據(jù)路由導(dǎo)航
public class ShardingNavigator {
    
    // 用戶表路由:根據(jù)user_id決定去哪個(gè)表
    public static String getUserTableName(long userId) {
        int tableIndex = (int) (userId % 16);
        return String.format("user_info_%02d", tableIndex);
    }
    
    // 訂單表路由:根據(jù)時(shí)間決定去哪個(gè)表
    public static String getOrderTableName(Date orderTime) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMM");
        return "order_" + sdf.format(orderTime);
    }
    
    // 組合查詢:跨表查詢就像組織家庭聚會(huì)
    public List<Order> getUserOrders(long userId, Date startTime, Date endTime) {
        List<Order> allOrders = new ArrayList<>();
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(startTime);
        
        // 遍歷時(shí)間范圍內(nèi)的所有月份表
        while (calendar.getTime().before(endTime)) {
            String tableName = getOrderTableName(calendar.getTime());
            String sql = "SELECT * FROM " + tableName + " WHERE user_id = ?";
            // 執(zhí)行查詢并添加到結(jié)果集
            // ...
            calendar.add(Calendar.MONTH, 1);
        }
        return allOrders;
    }
}

第5步:中間件配置——請(qǐng)個(gè)“萬能管家”

# ShardingSphere配置文件示例(YAML格式)
# 這位管家知道所有房間在哪
dataSources:
  ds0:
    url: jdbc:mysql://localhost:3306/user_villa?useSSL=false
    username: root
    password: your_password
  ds1:
    url: jdbc:mysql://localhost:3307/order_mansion?useSSL=false
    username: root
    password: your_password

shardingRule:
  tables:
    user_info:
      actualDataNodes: ds0.user_info_${0..15}
      tableStrategy:
        inline:
          shardingColumn: user_id
          algorithmExpression: user_info_${user_id % 16}
    order_info:
      actualDataNodes: ds1.order_${2024..2025}${1..12}
      tableStrategy:
        standard:
          shardingColumn: created_at
          preciseAlgorithmClassName: com.example.TimeShardingAlgorithm
  
  bindingTables:
    - user_info,order_info

第6步:數(shù)據(jù)遷移——搬家不能丟東西

-- 第一步:先抄家(備份)
CREATE TABLE order_mansion.order_202401_new LIKE order_mansion.order_202401;

-- 第二步:慢慢搬(增量遷移)
INSERT INTO order_mansion.order_202401_new
SELECT * FROM single_apartment.orders 
WHERE created_at >= '2024-01-01' 
  AND created_at < '2024-02-01';

-- 第三步:檢查有沒有落下的
SELECT 
    (SELECT COUNT(*) FROM single_apartment.orders 
     WHERE created_at >= '2024-01-01' AND created_at < '2024-02-01') as old_count,
    (SELECT COUNT(*) FROM order_mansion.order_202401_new) as new_count;

-- 第四步:切換門牌號(hào)(重命名)
RENAME TABLE 
    order_mansion.order_202401 TO order_mansion.order_202401_backup,
    order_mansion.order_202401_new TO order_mansion.order_202401;

第7步:全局ID生成——給每個(gè)數(shù)據(jù)發(fā)身份證

// 雪花算法:Twitter出品,必屬精品
public class SnowflakeIdGenerator {
    private final long twepoch = 1288834974657L;
    private final long workerIdBits = 5L;
    private final long datacenterIdBits = 5L;
    private final long sequenceBits = 12L;
    
    private long workerId;
    private long datacenterId;
    private long sequence = 0L;
    private long lastTimestamp = -1L;
    
    public synchronized long nextId() {
        long timestamp = timeGen();
        
        if (timestamp < lastTimestamp) {
            throw new RuntimeException("時(shí)間倒流了,檢查系統(tǒng)時(shí)間!");
        }
        
        if (lastTimestamp == timestamp) {
            sequence = (sequence + 1) & 4095;  // 2^12-1
            if (sequence == 0) {
                timestamp = tilNextMillis(lastTimestamp);
            }
        } else {
            sequence = 0L;
        }
        
        lastTimestamp = timestamp;
        
        return ((timestamp - twepoch) << 22) |
               (datacenterId << 17) |
               (workerId << 12) |
               sequence;
    }
    
    // 全局唯一,趨勢(shì)遞增,適合分庫分表
}

三、注意事項(xiàng)——別墅區(qū)的物業(yè)管理?xiàng)l例

分布式事務(wù):樓上轉(zhuǎn)賬,樓下扣款,必須同時(shí)成功或失敗

// 使用Seata等分布式事務(wù)解決方案
@GlobalTransactional
public void transferMoney(long fromUser, long toUser, BigDecimal amount) {
    // 1. 從用戶庫扣款
    // 2. 向訂單庫插入記錄
    // 要么都成功,要么都回滾
}

跨表查詢:想找張三的所有訂單?得問遍所有表!

-- 分表前:一步到位
SELECT * FROM orders WHERE user_id = 123;

-- 分表后:變成偵查行動(dòng)
SELECT * FROM order_202401 WHERE user_id = 123
UNION ALL
SELECT * FROM order_202402 WHERE user_id = 123
UNION ALL
-- ... 查遍所有月份表

JOIN操作:用戶表和訂單表在不同庫?只能業(yè)務(wù)層JOIN

// 1. 先從用戶庫查用戶
List<User> users = userDao.getUsers(condition);
List<Long> userIds = users.stream().map(User::getId).collect(Collectors.toList());

// 2. 再去訂單庫查這些用戶的訂單
List<Order> orders = orderDao.getOrdersByUserIds(userIds);

// 3. 在內(nèi)存中組裝
Map<Long, List<Order>> userOrdersMap = groupOrdersByUser(orders);

四、總結(jié)

分庫分表就像數(shù)據(jù)庫的成人禮,意味著你的業(yè)務(wù)從“小打小鬧”變成了“正經(jīng)事業(yè)”。但是:

不要過早優(yōu)化:如果你的數(shù)據(jù)還沒到百萬級(jí)別,別急著分表,就像不能因?yàn)閷砜赡茏兣?,現(xiàn)在就買XXL號(hào)褲子。

選擇合適的策略:按時(shí)間分?按地域分?按業(yè)務(wù)分?這就像選擇衣柜整理方式,有人喜歡按季節(jié),有人喜歡按顏色,適合的才是最好的。

準(zhǔn)備好工具:中間件(ShardingSphere、MyCat)是你的瑞士軍刀,監(jiān)控工具(Prometheus、Grafana)是你的健康檢測(cè)儀。

接受不完美:分庫分表后,事務(wù)復(fù)雜了,查詢麻煩了,運(yùn)維困難了。但這就是成長的代價(jià),就像長大后發(fā)現(xiàn)世界不是非黑即白。

最后提醒:分庫分表前,先試試這些“減肥方法”:

  • 加索引(給東西貼標(biāo)簽)
  • 優(yōu)化SQL(整理收納技巧)
  • 升級(jí)硬件(換個(gè)大房子)
  • 讀寫分離(男女分開用廁所)

只有當(dāng)這些都不夠用時(shí),才考慮分庫分表這個(gè)大工程。記住,好的架構(gòu)是演進(jìn)而來的,不是設(shè)計(jì)出來的。就像好的婚姻,需要慢慢磨合,不能一開始就分房睡(分庫)還分床(分表)!

祝你的數(shù)據(jù)庫從“小公寓”順利升級(jí)到“豪華別墅區(qū)”,住得寬敞,查得飛快!

以上就是一文詳解MySQL實(shí)現(xiàn)分庫分表的詳細(xì)步驟的詳細(xì)內(nèi)容,更多關(guān)于MySQL分庫分表的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • mysql中的limit用法有哪些(推薦)

    mysql中的limit用法有哪些(推薦)

    在我們使用查詢語句的時(shí)候,經(jīng)常要返回前幾條或者中間某幾行數(shù)據(jù),這個(gè)時(shí)候怎么辦呢,mysql已經(jīng)為我們提供了這樣一個(gè)功能,盡管語法邏輯很是怪異,這個(gè)功能就好比oracle里的rownum,但比mysql提供的這個(gè)LIMIT好用、好記和好理解多了,具體內(nèi)容一起通過本文看看吧
    2017-10-10
  • Mac上安裝MySQL過程分享

    Mac上安裝MySQL過程分享

    這篇文章主要介紹了Mac上安裝MySQL過程分享,本文共分4步完成,簡單易懂,需要的朋友可以參考下
    2014-11-11
  • mysql數(shù)據(jù)庫優(yōu)化總結(jié)(心得)

    mysql數(shù)據(jù)庫優(yōu)化總結(jié)(心得)

    本篇文章是對(duì)mysql數(shù)據(jù)庫優(yōu)化進(jìn)行了詳細(xì)的總結(jié)與介紹,需要的朋友參考下
    2013-06-06
  • 深入理解mysql的自連接和join關(guān)聯(lián)

    深入理解mysql的自連接和join關(guān)聯(lián)

    這篇文章主要給大家介紹了關(guān)于mysql的自連接和join關(guān)聯(lián)的相關(guān)資料,文中介紹的非常詳細(xì),相信對(duì)大家具有一定的參考價(jià)值,需要的朋友們下面來一起看看吧。
    2017-04-04
  • mysql優(yōu)化取隨機(jī)數(shù)據(jù)慢的方法

    mysql優(yōu)化取隨機(jī)數(shù)據(jù)慢的方法

    mysql取隨機(jī)數(shù)據(jù)慢,怎么辦?下面小編與大家一起來看看mysql取隨機(jī)數(shù)據(jù)慢優(yōu)化的過程。
    2013-11-11
  • MYSQL的日志文件詳解

    MYSQL的日志文件詳解

    MySQL的日志系統(tǒng)包括錯(cuò)誤日志、二進(jìn)制日志、慢查詢?nèi)罩?、通用查詢?nèi)罩?、重做日志和回滾日志,它們各自有不同的作用和性能影響,本文給大家介紹MYSQL的日志文件知識(shí),感興趣的朋友跟隨小編一起看看吧
    2026-01-01
  • mysql數(shù)據(jù)庫刪除重復(fù)數(shù)據(jù)只保留一條方法實(shí)例

    mysql數(shù)據(jù)庫刪除重復(fù)數(shù)據(jù)只保留一條方法實(shí)例

    這篇文章主要給大家介紹了關(guān)于mysql數(shù)據(jù)庫刪除重復(fù)數(shù)據(jù),只保留一條的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-03-03
  • mysql 5.7.17 安裝圖文教程(windows)

    mysql 5.7.17 安裝圖文教程(windows)

    這篇文章主要介紹了windows下mysql 5.7.17 安裝圖文教程,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-03-03
  • MySQL優(yōu)化常用的19種有效方法(推薦!)

    MySQL優(yōu)化常用的19種有效方法(推薦!)

    關(guān)于數(shù)據(jù)庫優(yōu)化,網(wǎng)上有不少資料和方法,但是不少質(zhì)量參差不齊,有些總結(jié)的不夠到位,內(nèi)容冗雜,下面這篇文章主要給大家介紹了關(guān)于MySQL優(yōu)化常用的19種有效方法,需要的朋友可以參考下
    2022-03-03
  • Mysql auto_increment 重新計(jì)數(shù)(讓id從1開始)

    Mysql auto_increment 重新計(jì)數(shù)(讓id從1開始)

    當(dāng)清空一個(gè)表的時(shí)候,重新插入數(shù)據(jù),發(fā)現(xiàn)auto_increment屬性的字段計(jì)數(shù)不是從1開始的時(shí)候,可以使用以下命令
    2012-12-12

最新評(píng)論

泸西县| 古丈县| 望奎县| 大丰市| 芜湖市| 开平市| 丰都县| 新乐市| 松滋市| 广南县| 福贡县| 平江县| 大竹县| 驻马店市| 垫江县| 中西区| 六盘水市| 蒙山县| 马龙县| 奉化市| 台江县| 柯坪县| 上饶县| 于都县| 安乡县| 云梦县| 成武县| 禹城市| 洛宁县| 房山区| 邯郸县| 仪陇县| 海兴县| 富川| 美姑县| 新邵县| 沭阳县| 库伦旗| 巩义市| 遂平县| 开江县|