1. 程式人生 > 資料庫 >MySQL資料庫優化之分表分庫操作例項詳解

MySQL資料庫優化之分表分庫操作例項詳解

本文例項講述了MySQL資料庫優化之分表分庫操作。分享給大家供大家參考,具體如下:

分表分庫

垂直拆分

垂直拆分就是要把表按模組劃分到不同資料庫表中(當然原則還是不破壞第三正規化),這種拆分在大型網站的演變過程中是很常見的。當一個網站還在很小的時候,只有小量的人來開發和維護,各模組和表都在一起,當網站不斷豐富和壯大的時候,也會變成多個子系統來支撐,這時就有按模組和功能把表劃分出來的需求。其實,相對於垂直切分更進一步的是服務化改造,說得簡單就是要把原來強耦合的系統拆分成多個弱耦合的服務,通過服務間的呼叫來滿足業務需求看,因此表拆出來後要通過服務的形式暴露出去,而不是直接呼叫不同模組的表,淘寶在架構不斷演變過程,最重要的一環就是服務化改造,把使用者、交易、店鋪、寶貝這些核心的概念抽取成獨立的服務,也非常有利於進行區域性的優化和治理,保障核心模組的穩定性

垂直拆分用於分散式場景。

水平拆分

上面談到垂直切分只是把表按模組劃分到不同資料庫,但沒有解決單表大資料量的問題,而水平切分就是要把一個表按照某種規則把資料劃分到不同表或資料庫裡。例如像計費系統,通過按時間來劃分表就比較合適,因為系統都是處理某一時間段的資料。而像SaaS應用,通過按使用者維度來劃分資料比較合適,因為使用者與使用者之間的隔離的,一般不存在處理多個使用者資料的情況,簡單的按user_id範圍來水平切分
通俗理解:水平拆分行,行資料拆分到不同表中, 垂直拆分列,表資料拆分到不同表中

水平分割案例

思路:在大型電商系統中,每天的會員人數不斷的增加。達到一定瓶頸後如何優化查詢。
可能大家會想到索引,萬一使用者量達到上億級別,如何進行優化呢?

使用水平分割拆分資料庫表。

如何使用水平拆分資料庫

使用水平分割拆分表,具體根據業務需求,有的按照註冊時間、取摸、賬號規則、年份等。

使用取摸方式分表

首先我建立三張表 user0 / user1 /user2,然後我再建立 uuid表,該表的作用就是提供自增的id。

create table user0(
id int unsigned primary key,name varchar(32) not null default '',pwd varchar(32) not null default '')
engine=myisam charset utf8;
create table user1(
id int unsigned primary key,pwd varchar(32) not null default '')
engine=myisam charset utf8;
create table user2(
id int unsigned primary key,pwd varchar(32) not null default '')
engine=myisam charset utf8;
create table uuid(
id int unsigned primary key auto_increment)engine=myisam charset utf8;

建立一個demo專案

POM檔案

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.3.3.RELEASE</version>
    </parent>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>

Service程式碼

@Service
public class UserService {
    @Autowired
    private JdbcTemplate jdbcTemplate;
    public String regit(String name,String pwd) {
        // 1.先獲取到 自定增長ID
        String idInsertSQL = "INSERT INTO uuid VALUES (NULL);";
        jdbcTemplate.update(idInsertSQL);
        Long insertId = jdbcTemplate.queryForObject("select last_insert_id()",Long.class);
        // 2.判斷儲存表名稱
        String tableName = "user" + insertId % 3;
        // 3.註冊資料
        String insertUserSql = "INSERT INTO " + tableName + " VALUES ('" + insertId + "','" + name + "','" + pwd
                + "');";
        System.out.println("insertUserSql:" + insertUserSql);
        jdbcTemplate.update(insertUserSql);
        return "success";
    }
    public String get(Long id) {
        String tableName = "user" + id % 3;
        String sql = "select name from " + tableName + " where id="+id;
        System.out.println("SQL:" + sql);
        String name = jdbcTemplate.queryForObject(sql,String.class);
        return name;
    }
}

Controller

@RestController
public class UserController {
    @Autowired
    private UserService userService;
    @RequestMapping("/regit")
    public String regit(String name,String pwd) {
        return userService.regit(name,pwd);
    }
    @RequestMapping("/get")
    public String get(Long id) {
        String name = userService.get(id);
        return name;
    }
}

更多關於MySQL相關內容感興趣的讀者可檢視本站專題:《MySQL查詢技巧大全》、《MySQL常用函式大彙總》、《MySQL日誌操作技巧大全》、《MySQL事務操作技巧彙總》、《MySQL儲存過程技巧大全》及《MySQL資料庫鎖相關技巧彙總》

希望本文所述對大家MySQL資料庫計有所幫助。