目錄
1 分区的类型
1.1RANGE分区
1.2LIST分区
1.3 HASH分区
1.4 KEY分区
1.5 更多的知识
2 使用分区表的限制
3 使用分区表的“陷阱”
4 优化查询语句
首頁 資料庫 mysql教程 高性能MySql进化论(十二):Mysql中分区表的使用总结_MySQL

高性能MySql进化论(十二):Mysql中分区表的使用总结_MySQL

Jun 01, 2016 pm 01:26 PM

bitsCN.com

当数据量非常大时(表的容量到达GB或者是TB),如果仍然采用索引的方式来优化查询,由于索引本生的消耗以及大量的索引碎片的产生,查询的过程会导致大量的随机I/O的产生,在这种场景下除非可以很好的利用覆盖索引,否则由于在查询的过程中需要根据索引回数据表查询,会导致性能受到很大的影响,这时可以考虑通过分区表的策略来提高查询的性能。

不同的数据库管理系统对分区的实现可能有所区别,本文主要以MYSQL为基础

1 分区的类型

1.1RANGE分区

按照RANGE分区的表是通过如下一种方式进行分区的,每个分区包含那些分区表达式的值位于一个给定的连续区间内的行。这些区间要连续且不能相互重叠,使用VALUES LESS THAN操作符来进行定义

假定你想基于每个雇员离开公司的年份来分割表,也就是说,YEAR(separated)的值。实现这种分区模式的CREATE TABLE 语句的一个例子如下所示。

例如,你可能决定通过添加一个PARTITION BY RANGE子句把这个表分割成4个区间

CREATE TABLE employees (    id INT NOT NULL,    fname VARCHAR(30),    lname VARCHAR(30),    hired DATE NOT NULL DEFAULT '1970-01-01',    separated DATE NOT NULL DEFAULT '9999-12-31',    job_code INT,    store_id INT)PARTITION BY RANGE (YEAR(separated)) (    PARTITION p0 VALUES LESS THAN (1991),    PARTITION p1 VALUES LESS THAN (1996),    PARTITION p2 VALUES LESS THAN (2001),    PARTITION p3 VALUES LESS THAN MAXVALUE);
登入後複製
插入一些测试数据后发现P1的数据文件明显增大
mysql> DELIMITER $$mysql> DROP PROCEDURE IF EXISTS SampleProc$$Query OK, 0 rows affected (0.00 sec)mysql> CREATE PROCEDURE SampleProc()    -> BEGIN    ->  DECLARE x INT;    ->  SET x = 1000;    ->  WHILE x<= 2000 DO    ->          insert into employees(id,fname,lname,hired,separated,job_code,store_id) values(x,concat(&#39;firstname&#39;,x),concat(&#39;ai&#39;,x),&#39;1994-01-01&#39;,&#39;1995-01-01&#39;,10,20);    ->          SET  x = x + 1;    ->  END WHILE;    -> END$$Query OK, 0 rows affected (0.00 sec)mysql> call SampleProc() $$Query OK, 1 row affected (22.55 sec)mysql> delimiter ; 
登入後複製

RANGE分区在如下场合特别有用:

· 当需要删除“旧的”数据时。如果你使用上面最近的那个例子给出的分区方案,你只需简单地使用 “ALTER TABLEemployees DROP PARTITION p0;”来删除所有在1991年前就已经停止工作的雇员相对应的所有行。(更多信息请参见13.1.2节,“ALTER TABLE语法” 和18.3节,“分区管理”)。对于有大量行的表,这比运行一个如“DELETE FROM employees WHERE YEAR(separated) <= 1990;”这样的一个DELETE查询要有效得多。

· 想要使用一个包含有日期或时间值,或包含有从一些其他级数开始增长的值的列。

· 经常运行直接依赖于用于分割表的列的查询。例如,当执行一个如“SELECT COUNT(*) FROM employees WHERE YEAR(separated) = 2000 GROUP BYstore_id;”这样的查询时,MySQL可以很迅速地确定只有分区p2需要扫描,这是因为余下的分区不可能包含有符合该WHERE子句的任何记录。

· 分区表达式可以是MySQL 中有效的任何函数或其他表达式,只要它们返回一个既非常数、也非随机数的整数

1.2LIST分区

MySQL中的LIST分区在很多方面类似于RANGE分区。和按照RANGE分区一样,每个分区必须明确定义。它们的主要区别在于,LIST分区中每个分区的定义和选择是基于某列的值从属于一个值列表集中的一个值,而RANGE分区是从属于一个连续区间值的集合。LIST分区通过使用“PARTITION BY LIST(expr)”来实现,其中“expr” 是某列值或一个基于某个列值、并返回一个整数值的表达式,然后通过“VALUES IN (value_list)”的方式来定义每个分区,其中“value_list”是一个通过逗号分隔的整数列表。

假定有20个音像店,分布在4个有经销权的地区,如下表所示:

地区

商店ID 号

北区

3, 5, 6, 9, 17

东区

1, 2, 10, 11, 19, 20

西区

4, 12, 13, 14, 18

中心区

7, 8, 15, 16

要按照属于同一个地区商店的行保存在同一个分区中的方式来分割表,可以使用下面的“CREATETABLE”语句

CREATE TABLE employees (    id INT NOT NULL,    fname VARCHAR(30),    lname VARCHAR(30),    hired DATE NOT NULL DEFAULT &#39;1970-01-01&#39;,    separated DATE NOT NULL DEFAULT &#39;9999-12-31&#39;,    job_code INT,    store_id INT)PARTITION BY LIST(store_id)    PARTITION pNorth VALUES IN (3,5,6,9,17),    PARTITION pEast VALUES IN (1,2,10,11,19,20),    PARTITION pWest VALUES IN (4,12,13,14,18),    PARTITION pCentral VALUES IN (7,8,15,16));
登入後複製

相关的操作和range 分区类似,但有以下问题需要注意

· 在MySQL 5.1中,当使用LIST分区时,有可能只能匹配整数列表。

· 如果试图插入列值(或分区表达式的返回值)不在分区值列表中的一行时,那么“INSERT”查询将失败并报错。例如,假定LIST分区的采用上面的方案,下面的查询将失败:

· LIST分区没有类似如“VALUESLESS THAN MAXVALUE”这样的包含其他值在内的定义。将要匹配的任何值都必须在值列表中找到

1.3 HASH分区

HASH分区主要用来确保数据在预先确定数目的分区中平均分布。在RANGE和LIST分区中,必须明确指定一个给定的列值或列值集合应该保存在哪个分区中;而在HASH分区中,MySQL 自动完成这些工作,你所要做的只是基于将要被哈希的列值指定一个列值或表达式,以及指定被分区的表将要被分割成的分区数量。

例如,下面的语句创建了一个使用基于“store_id”列进行哈希处理的表,该表被分成了4个分区:

CREATE TABLE employees (    id INT NOT NULL,    fname VARCHAR(30),    lname VARCHAR(30),    hired DATE NOT NULL DEFAULT &#39;1970-01-01&#39;,    separated DATE NOT NULL DEFAULT &#39;9999-12-31&#39;,    job_code INT,    store_id INT)PARTITION BY HASH(store_id)PARTITIONS 4;
登入後複製

如果没有包括一个PARTITIONS子句,那么分区的数量将默认为1

1.4 KEY分区

KEY进行分区类似于按照HASH分区,除了HASH分区使用的用户定义的表达式,而KEY分区的 哈希函数是由MySQL 服务器提供。MySQL 簇(Cluster)使用函数MD5()来实现KEY分区;对于使用其他存储引擎的表,服务器使用其自己内部的 哈希函数,这些函数是基于与PASSWORD()一样的运算法则。

“CREATETABLE ... PARTITION BY KEY”的语法规则类似于创建一个通过HASH分区的表的规则。它们唯一的区别在于使用的关键字是KEY而不是HASH,并且KEY分区只采用一个或多个列名的一个列表。

通过线性KEY分割一个表也是可能的。下面是一个简单的例子:

CREATE TABLE tk (    col1 INT NOT NULL,    col2 CHAR(5),    col3 DATE) PARTITION BY LINEAR KEY (col1)PARTITIONS 3;
登入後複製

在KEY分区中使用关键字LINEAR和在HASH分区中使用具有同样的作用,分区的编号是通过2的幂(powers-of-two)算法得到,而不是通过模数算法

1.5 更多的知识

上面列出的仅仅是常用的分区策略的用法,当创建了分区后往往还要对分区进行维护,具体请参见:

http://dev.mysql.com/doc/refman/5.1/zh/partitioning.html#partitioning-hash

无论使用何种类型的分区,分区总是在创建时就自动的顺序编号,且从0开始记录,记住这一点非常重要。当有一新行插入到一个分区表中时,就是使用这些分区编号来识别正确的分区。例如,如果你的表使用4个分区,那么这些分区就编号为0, 1, 2, 和3。对于RANGE和LIST分区类型,确认每个分区编号都定义了一个分区,很有必要。对HASH分区,使用的用户函数必须返回一个大于0的整数值。对于KEY分区,这个问题通过MySQL服务器内部使用的 哈希函数自动进行处理。

2 使用分区表的限制

· 一个数据表最多只能有1024个分区

· 在MYSQL5.1 版本中分区表达式的结果必须是整数,在MYSQL5.5分区表达式可以使用列

· 如果分区字段中有主键或者是唯一索引列,则所有的主键或者是唯一索引列必须全部包含进来

· 分区表无法使用外键

· 对于同一个表的各个分区表必须使用相同的存储引擎

· 分区函数有限制,只可以是MySQL 中有效的任何函数或其他表达式,且它们返回一个既非常数、也非随机数的整数

· 某些存储引擎不支持分区

3 使用分区表的“陷阱”

在数据量非常大的时候使用分区表可以使性能有较好的改善,但是前提是必须能有效的规避下面列出的一些陷阱

· NULL值

MySQL 中的分区在禁止空值(NULL)上没有进行处理,无论它是一个列值还是一个用户定义表达式的值。一般而言,对于NULL,或者是当表达式接收非法值时(e.g. YEAR(‘asdf-12-12’))返回的结果都是NULL,在这种情况下MySQL 把NULL视为0,如果大量的记录存在这种情况,最终会导致大量的记录都集中在一个分区中,也也就违背了分区的初衷。

如果你希望回避这种做法,你应该在设计表时不允许空值;最可能的方法是,通过声明列“NOT NULL”来实现这一点。

· 分区列和索引列不匹配

如果定义的索引列和分区列不匹配,则会导致查询无法进行分区过滤。例如在列a上定义分区,在列b上定义索引,因为每个分区都有独立的索引,所以扫描索引时需要扫描每个分区。

应该避免建立和分区列不匹配的索引,除非查询中包含了可以过滤分区的条件。

· 选择分区的成本很高

对于Range 和list类型的分区,每次进行操作时都需要遍历所有的分区条件,以判断相关的记录是属于哪个分区,如果分区的数量很多,会在选择分区上浪费较多的资源

为了避免这种情况 可以限制分区的数目(

· 锁住底层表的成本很高

在查询访问分区表的时候,MYSQL会打开并锁住所有的底层表,该操作时再分区过滤之前发生而且和分区类型无关,会影响所有的分区查询。

可以通过批量更新的方式来降低该操作的次数,同时也需要限制分区的数目

· 维护成本高

增加/删除分区很快捷,但是重组或者是alter分区的过程类似于alter table,会进行大量的数据复制操作,效率很低。

4 优化查询语句

对于分区表的访问,最重要的一点是要在where条件中包含分区列,即使看起来是多余的,只有这样才能过滤不需要的分区,否则会访问所以的分区表。

看一个简单的例子。

Employees表使用store_id作为范围分区的条件,如果不使用store_id作为where条件,会查询所有的分区

Store_id作为where条件时,只查询对应的分区

关于where条件中的表达式有几点需要注意

· 单纯的使用分区列

Where条件中分区列必须是未经函数处理的,如果where条件写成where YEAR(store_id), 则分区过滤会失效,且查询时会检查所有的分区。这一点和索引类似

· 关联查询

如果分区表是关联操作的第二张表,且关联条件是分区建,则MYSQL只会在对应的分区里进行匹配

bitsCN.com
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

熱門話題

Java教學
1664
14
CakePHP 教程
1422
52
Laravel 教程
1316
25
PHP教程
1267
29
C# 教程
1239
24
與MySQL中使用索引相比,全表掃描何時可以更快? 與MySQL中使用索引相比,全表掃描何時可以更快? Apr 09, 2025 am 12:05 AM

全表掃描在MySQL中可能比使用索引更快,具體情況包括:1)數據量較小時;2)查詢返回大量數據時;3)索引列不具備高選擇性時;4)複雜查詢時。通過分析查詢計劃、優化索引、避免過度索引和定期維護表,可以在實際應用中做出最優選擇。

mysql:簡單的概念,用於輕鬆學習 mysql:簡單的概念,用於輕鬆學習 Apr 10, 2025 am 09:29 AM

MySQL是一個開源的關係型數據庫管理系統。 1)創建數據庫和表:使用CREATEDATABASE和CREATETABLE命令。 2)基本操作:INSERT、UPDATE、DELETE和SELECT。 3)高級操作:JOIN、子查詢和事務處理。 4)調試技巧:檢查語法、數據類型和權限。 5)優化建議:使用索引、避免SELECT*和使用事務。

MySQL:初學者的數據管理易用性 MySQL:初學者的數據管理易用性 Apr 09, 2025 am 12:07 AM

MySQL適合初學者使用,因為它安裝簡單、功能強大且易於管理數據。 1.安裝和配置簡單,適用於多種操作系統。 2.支持基本操作如創建數據庫和表、插入、查詢、更新和刪除數據。 3.提供高級功能如JOIN操作和子查詢。 4.可以通過索引、查詢優化和分錶分區來提升性能。 5.支持備份、恢復和安全措施,確保數據的安全和一致性。

MySQL的角色:Web應用程序中的數據庫 MySQL的角色:Web應用程序中的數據庫 Apr 17, 2025 am 12:23 AM

MySQL在Web應用中的主要作用是存儲和管理數據。 1.MySQL高效處理用戶信息、產品目錄和交易記錄等數據。 2.通過SQL查詢,開發者能從數據庫提取信息生成動態內容。 3.MySQL基於客戶端-服務器模型工作,確保查詢速度可接受。

MySQL:世界上最受歡迎的數據庫的簡介 MySQL:世界上最受歡迎的數據庫的簡介 Apr 12, 2025 am 12:18 AM

MySQL是一種開源的關係型數據庫管理系統,主要用於快速、可靠地存儲和檢索數據。其工作原理包括客戶端請求、查詢解析、執行查詢和返回結果。使用示例包括創建表、插入和查詢數據,以及高級功能如JOIN操作。常見錯誤涉及SQL語法、數據類型和權限問題,優化建議包括使用索引、優化查詢和分錶分區。

說明InnoDB重做日誌和撤消日誌的作用。 說明InnoDB重做日誌和撤消日誌的作用。 Apr 15, 2025 am 12:16 AM

InnoDB使用redologs和undologs確保數據一致性和可靠性。 1.redologs記錄數據頁修改,確保崩潰恢復和事務持久性。 2.undologs記錄數據原始值,支持事務回滾和MVCC。

MySQL的位置:數據庫和編程 MySQL的位置:數據庫和編程 Apr 13, 2025 am 12:18 AM

MySQL在數據庫和編程中的地位非常重要,它是一個開源的關係型數據庫管理系統,廣泛應用於各種應用場景。 1)MySQL提供高效的數據存儲、組織和檢索功能,支持Web、移動和企業級系統。 2)它使用客戶端-服務器架構,支持多種存儲引擎和索引優化。 3)基本用法包括創建表和插入數據,高級用法涉及多表JOIN和復雜查詢。 4)常見問題如SQL語法錯誤和性能問題可以通過EXPLAIN命令和慢查詢日誌調試。 5)性能優化方法包括合理使用索引、優化查詢和使用緩存,最佳實踐包括使用事務和PreparedStatemen

為什麼要使用mysql?利益和優勢 為什麼要使用mysql?利益和優勢 Apr 12, 2025 am 12:17 AM

選擇MySQL的原因是其性能、可靠性、易用性和社區支持。 1.MySQL提供高效的數據存儲和檢索功能,支持多種數據類型和高級查詢操作。 2.採用客戶端-服務器架構和多種存儲引擎,支持事務和查詢優化。 3.易於使用,支持多種操作系統和編程語言。 4.擁有強大的社區支持,提供豐富的資源和解決方案。

See all articles