데이터 베이스 MySQL 튜토리얼 MySQL基于时间字段进行分区的方案总结_MySQL

MySQL基于时间字段进行分区的方案总结_MySQL

May 27, 2016 pm 01:46 PM
필드 계획 시간

MySQL支持的分区类型一共有四种:RANGE,LIST,HASH,KEY。其中,RANGE又可分为原生RANGE和RANGE COLUMNS,LIST分为原生LIST和LIST COLUMNS,HASH分为原生HASH和LINEAR HASH,KEY包含原生KEY和LINEAR HASH。关于这些分区之间的差别,改日另写文章进行阐述。

 

最近,碰到一个需求,要对表的时间字段(类型:datetime)基于天进行分区。于是遍历MySQL官方文档分区章节,总结如下:

 

实现方式

 

主要是以下几种:

 

1. 基于RANGE

 

2. 基于RANGE COLUMNS

 

3. 基于HASH

 

测试数据 

 

为了测试以上三种方案,特构造了100万的测试数据,放在test表中,test表只有两列:id和hiredate,其中hiredate只包含10天的数据,从2015-12-01到2015-12-10。具体信息如下:

 

mysql> show create table test\G
*************************** 1. row ***************************
       Table: test
Create Table: CREATE TABLE `test` (
  `id` int(11) DEFAULT NULL,
  `hiredate` datetime DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1
1 row in set (0.00 sec)

mysql> select min(hiredate),max(hiredate) from test;
+---------------------+---------------------+
| min(hiredate)       | max(hiredate)       |
+---------------------+---------------------+
| 2015-12-01 00:00:00 | 2015-12-10 23:59:56 |
+---------------------+---------------------+
1 row in set (0.44 sec)

mysql> select date(hiredate),count(*) from test group by date(hiredate);
+----------------+----------+
| date(hiredate) | count(*) |
+----------------+----------+
| 2015-12-01     |    99963 |
| 2015-12-02     |   100032 |
| 2015-12-03     |   100150 |
| 2015-12-04     |    99989 |
| 2015-12-05     |    99908 |
| 2015-12-06     |    99897 |
| 2015-12-07     |   100137 |
| 2015-12-08     |   100171 |
| 2015-12-09     |    99851 |
| 2015-12-10     |    99902 |
+----------------+----------+
10 rows in set (0.98 sec)
로그인 후 복사

测试的维度

测试的维度主要从两个方面进行,

一、分区剪裁

针对特定的查询,是否能进行分区剪裁(即只查询相关的分区,而不是所有分区)

二、查询时间

鉴于该批测试数据是静止的(即没有并发进行的insert,update和delete操作),数据量也不太大,从这个维度来考量貌似意义也不是很大。

因此,重点测试第一个维度。

基于RANGE的分区方案

在这里,选用了TO_DAYS函数

CREATE TABLE range_datetime(
    id INT,
    hiredate DATETIME
)
PARTITION BY RANGE (TO_DAYS(hiredate) ) (
    PARTITION p1 VALUES LESS THAN ( TO_DAYS('20151202') ),
    PARTITION p2 VALUES LESS THAN ( TO_DAYS('20151203') ),
    PARTITION p3 VALUES LESS THAN ( TO_DAYS('20151204') ),
    PARTITION p4 VALUES LESS THAN ( TO_DAYS('20151205') ),
    PARTITION p5 VALUES LESS THAN ( TO_DAYS('20151206') ),
    PARTITION p6 VALUES LESS THAN ( TO_DAYS('20151207') ),
    PARTITION p7 VALUES LESS THAN ( TO_DAYS('20151208') ),
    PARTITION p8 VALUES LESS THAN ( TO_DAYS('20151209') ),
    PARTITION p9 VALUES LESS THAN ( TO_DAYS('20151210') ),
    PARTITION p10 VALUES LESS THAN ( TO_DAYS('20151211') )
);
로그인 후 복사

插入数据并查看特定查询的执行计划

mysql> insert into range_datetime select * from test;                                                                    
Query OK, 1000000 rows affected (8.15 sec)
Records: 1000000  Duplicates: 0  Warnings: 0

mysql> explain partitions select * from range_datetime where hiredate >= &#39;20151207124503&#39; and hiredate<=&#39;20151210111230&#39;; 
+----+-------------+----------------+--------------+------+---------------+------+---------+------+--------+-------------+
| id | select_type | table          | partitions   | type | possible_keys | key  | key_len | ref  | rows   | Extra       |
+----+-------------+----------------+--------------+------+---------------+------+---------+------+--------+-------------+
|  1 | SIMPLE      | range_datetime | p7,p8,p9,p10 | ALL  | NULL          | NULL | NULL    | NULL | 400061 | Using where |
+----+-------------+----------------+--------------+------+---------------+------+---------+------+--------+-------------+
1 row in set (0.03 sec)
로그인 후 복사

注意执行计划中的partitions的内容,只查询了p7,p8,p9,p10三个分区,由此来看,使用to_days函数确实可以实现分区裁剪。

基于RANGE COLUMNS的分区方案

RANGE COLUMNS可以直接基于列,而无需像上述RANGE那种,分区的对象只能为整数。

创表语句如下:

CREATE TABLE range_columns ( 
    id INT,
    hiredate DATETIME
)
PARTITION BY RANGE COLUMNS(hiredate) (
    PARTITION p1 VALUES LESS THAN ( &#39;20151202&#39; ),
    PARTITION p2 VALUES LESS THAN ( &#39;20151203&#39; ),
    PARTITION p3 VALUES LESS THAN ( &#39;20151204&#39; ),
    PARTITION p4 VALUES LESS THAN ( &#39;20151205&#39; ),
    PARTITION p5 VALUES LESS THAN ( &#39;20151206&#39; ),
    PARTITION p6 VALUES LESS THAN ( &#39;20151207&#39; ),
    PARTITION p7 VALUES LESS THAN ( &#39;20151208&#39; ),
    PARTITION p8 VALUES LESS THAN ( &#39;20151209&#39; ),
    PARTITION p9 VALUES LESS THAN ( &#39;20151210&#39; ),
    PARTITION p10 VALUES LESS THAN (&#39;20151211&#39; )
);
로그인 후 복사

插入数据并查看上述查询的执行计划

mysql> insert into range_columns select * from test;                                                                    
Query OK, 1000000 rows affected (9.20 sec)
Records: 1000000  Duplicates: 0  Warnings: 0

mysql> explain partitions select * from range_columns where hiredate >= &#39;20151207124503&#39; and hiredate<=&#39;20151210111230&#39;; 
+----+-------------+---------------+--------------+------+---------------+------+---------+------+--------+-------------+
| id | select_type | table         | partitions   | type | possible_keys | key  | key_len | ref  | rows   | Extra       |
+----+-------------+---------------+--------------+------+---------------+------+---------+------+--------+-------------+
|  1 | SIMPLE      | range_columns | p7,p8,p9,p10 | ALL  | NULL          | NULL | NULL    | NULL | 400210 | Using where |
+----+-------------+---------------+--------------+------+---------------+------+---------+------+--------+-------------+
1 row in set (0.11 sec)
로그인 후 복사

同样,使用该分区方案也实现了分区剪裁。

基于HASH的分区方案

因HASH分区对象同样只能为整数,所以我们无法像上述RANGE COLUMNS那种直接引用列,在这里,同样用了TO_DAYS函数进行转换。

创表语句如下:

CREATE TABLE hash_datetime (
   id INT,
   hiredate DATETIME
)
PARTITION BY HASH( TO_DAYS(hiredate) )
PARTITIONS 10;
로그인 후 복사

插入数据并查看上述查询的执行计划

mysql> insert into hash_datetime select * from test;
Query OK, 1000000 rows affected (9.43 sec)
Records: 1000000  Duplicates: 0  Warnings: 0

mysql> explain partitions select * from hash_datetime where hiredate >= &#39;20151207124503&#39; and hiredate<=&#39;20151210111230&#39;;
+----+-------------+---------------+-------------------------------+------+---------------+------+---------+------+---------+-------------+
| id | select_type | table         | partitions                    | type | possible_keys | key  | key_len | ref  | rows    | Extra       |
+----+-------------+---------------+-------------------------------+------+---------------+------+---------+------+---------+-------------+
|  1 | SIMPLE      | hash_datetime | p0,p1,p2,p3,p4,p5,p6,p7,p8,p9 | ALL  | NULL          | NULL | NULL    | NULL | 1000500 | Using where |
+----+-------------+---------------+-------------------------------+------+---------------+------+---------+------+---------+-------------+
1 row in set (0.00 sec)
로그인 후 복사

不难看出,使用hash分区并不能有效的实现分区裁剪,至少在本例,基于天的需求中如此。

以上三种方案都是基于datetime的,那么,对于timestamp类型,又该如何选择呢?

事实上,MySQL提供了一种基于UNIX_TIMESTAMP函数的RANGE分区方案,而且,只能使用UNIX_TIMESTAMP函数,如果使用其它函数,譬如to_days,会报如下错误:“ERROR 1486 (HY000): Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed”。

而且官方文档中也提到“Any other expressions involving TIMESTAMP values are not permitted. (See Bug #42849.)”。

下面来测试一下基于UNIX_TIMESTAMP函数的RANGE分区方案,看其能否实现分区裁剪。

针对TIMESTAMP的分区方案

创表语句如下:

CREATE TABLE range_timestamp (
    id INT,
    hiredate TIMESTAMP
)
PARTITION BY RANGE ( UNIX_TIMESTAMP(hiredate) ) (
    PARTITION p1 VALUES LESS THAN ( UNIX_TIMESTAMP(&#39;2015-12-02 00:00:00&#39;) ),
    PARTITION p2 VALUES LESS THAN ( UNIX_TIMESTAMP(&#39;2015-12-03 00:00:00&#39;) ),
    PARTITION p3 VALUES LESS THAN ( UNIX_TIMESTAMP(&#39;2015-12-04 00:00:00&#39;) ),
    PARTITION p4 VALUES LESS THAN ( UNIX_TIMESTAMP(&#39;2015-12-05 00:00:00&#39;) ),
    PARTITION p5 VALUES LESS THAN ( UNIX_TIMESTAMP(&#39;2015-12-06 00:00:00&#39;) ),
    PARTITION p6 VALUES LESS THAN ( UNIX_TIMESTAMP(&#39;2015-12-07 00:00:00&#39;) ),
    PARTITION p7 VALUES LESS THAN ( UNIX_TIMESTAMP(&#39;2015-12-08 00:00:00&#39;) ),
    PARTITION p8 VALUES LESS THAN ( UNIX_TIMESTAMP(&#39;2015-12-09 00:00:00&#39;) ),
    PARTITION p9 VALUES LESS THAN ( UNIX_TIMESTAMP(&#39;2015-12-10 00:00:00&#39;) ),
    PARTITION p10 VALUES LESS THAN (UNIX_TIMESTAMP(&#39;2015-12-11 00:00:00&#39;) )
);
로그인 후 복사

插入数据并查看上述查询的执行计划

mysql> insert into range_timestamp select * from test;
Query OK, 1000000 rows affected (13.25 sec)
Records: 1000000  Duplicates: 0  Warnings: 0

mysql> explain partitions select * from range_timestamp where hiredate >= &#39;20151207124503&#39; and hiredate<=&#39;20151210111230&#39;;
+----+-------------+-----------------+--------------+------+---------------+------+---------+------+--------+-------------+
| id | select_type | table           | partitions   | type | possible_keys | key  | key_len | ref  | rows   | Extra       |
+----+-------------+-----------------+--------------+------+---------------+------+---------+------+--------+-------------+
|  1 | SIMPLE      | range_timestamp | p7,p8,p9,p10 | ALL  | NULL          | NULL | NULL    | NULL | 400448 | Using where |
+----+-------------+-----------------+--------------+------+---------------+------+---------+------+--------+-------------+
1 row in set (0.00 sec)
로그인 후 복사

 

同样也能实现分区裁剪。

 

 

总结:

 

1. 经过对比,个人倾向于第二种方案,即基于RANGE COLUMNS的分区实现。

 

2. 在5.7版本之前,对于DATA和DATETIME类型的列,如果要实现分区裁剪,只能使用YEAR() 和TO_DAYS()函数,在5.7版本中,又新增了TO_SECONDS()函数。

 

3. 其实LIST也能实现基于天的分区方案,但在这个需求上,相比于RANGE,还是显得很鸡肋。

 

4. TIMESTAMP类型的列,只能基于UNIX_TIMESTAMP函数进行分区,切记!

본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.

핫 AI 도구

Undresser.AI Undress

Undresser.AI Undress

사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover

AI Clothes Remover

사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool

Undress AI Tool

무료로 이미지를 벗다

Clothoff.io

Clothoff.io

AI 옷 제거제

Video Face Swap

Video Face Swap

완전히 무료인 AI 얼굴 교환 도구를 사용하여 모든 비디오의 얼굴을 쉽게 바꾸세요!

뜨거운 도구

메모장++7.3.1

메모장++7.3.1

사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전

SublimeText3 중국어 버전

중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기

스튜디오 13.0.1 보내기

강력한 PHP 통합 개발 환경

드림위버 CS6

드림위버 CS6

시각적 웹 개발 도구

SublimeText3 Mac 버전

SublimeText3 Mac 버전

신 수준의 코드 편집 소프트웨어(SublimeText3)

Douyin 레벨 10 조명 표지판의 가격은 얼마입니까? 레벨 10 팬사인회 제작에는 며칠이 소요되나요? Douyin 레벨 10 조명 표지판의 가격은 얼마입니까? 레벨 10 팬사인회 제작에는 며칠이 소요되나요? Mar 11, 2024 pm 05:37 PM

Douyin 플랫폼에서는 많은 사용자가 레벨 인증을 받기를 열망하고 있으며 레벨 10 표시등은 Douyin에 대한 사용자의 영향력과 인식을 보여줍니다. 이 기사에서는 사용자가 프로세스를 더 잘 이해할 수 있도록 Douyin의 레벨 10 라이트 보드 가격과 이 레벨에 도달하는 데 걸리는 시간을 자세히 살펴보겠습니다. 1. 레벨 10 Douyin 라이트 사인의 가격은 얼마입니까? Douyin의 10단계 전광판 가격은 시장 변동과 수요 공급에 따라 달라질 수 있으며, 일반적인 가격은 수천 위안에서 만 위안까지 다양합니다. 이 가격에는 주로 조명 사인 자체 비용과 가능한 서비스 수수료가 포함됩니다. 사용자는 Douyin의 공식 채널이나 제3자 서비스 대행사를 통해 레벨 10 조명 간판을 구매할 수 있지만, 허위 또는 사기 거래를 피하기 위해 구매 시 법적 채널에 주의해야 합니다. 2. 레벨 10 팬사인을 만드는데 며칠이 걸리나요? 레벨 10 신호등에 도달하세요

검증 가능한 AI를 향하여: 형식적 방법의 5가지 과제 검증 가능한 AI를 향하여: 형식적 방법의 5가지 과제 Apr 09, 2023 pm 02:01 PM

인공지능(Artificial Intelligence)은 학습, 문제 해결, 합리적 사고와 행동 등 지능과 직관적으로 관련된 인간의 일부 기능을 포함하여 인간의 지능을 모방하려는 컴퓨팅 시스템입니다. 광범위하게 해석되는 AI라는 용어는 기계 학습과 같이 밀접하게 관련된 여러 분야를 포괄합니다. AI를 많이 활용하는 시스템은 의료, 교통, 금융, 소셜 네트워크, 전자상거래, 교육 등의 분야에서 상당한 사회적 영향을 미치고 있습니다. 이러한 사회적 영향의 증가는 인공지능 소프트웨어의 오류, 사이버 공격, 인공지능 시스템 보안 등 일련의 위험과 우려를 불러일으키기도 했습니다. 따라서 AI 시스템 검증 문제, 더 나아가 신뢰할 수 있는 AI라는 주제가 연구계의 관심을 끌기 시작했습니다. '검증가능한 AI'가 확인됐다

엘든 링을 클리어하는 데 얼마나 걸리나요? 엘든 링을 클리어하는 데 얼마나 걸리나요? Mar 11, 2024 pm 12:50 PM

플레이어는 Elden's Circle에서 플레이할 때 게임의 주요 줄거리를 경험하고 게임 성과를 수집할 수 있습니다. 많은 플레이어는 Elden's Circle을 클리어하는 데 시간이 얼마나 걸리는지 모릅니다. 엘든 링을 클리어하는데 얼마나 걸리나요? 답변: 30시간. 1. 이 30시간 통관시간은 마스터급 스피드패스를 의미하지는 않지만, 많은 과정을 생략하기도 합니다. 2. 더 나은 게임 경험을 원하거나 전체 줄거리를 경험하고 싶다면 반드시 지속 시간에 더 많은 시간을 할애해야 합니다. 3. 모두 모으는 데에는 약 100~120시간 정도 소요됩니다. 4. 본선만 타고 BOSS 브러싱을 하면 50~60시간 정도 소요됩니다. 5. 모든 것을 경험하고 싶다면: 기본 시간 150시간.

리눅스가 시스템 시간을 재설정할 수 있나요? 리눅스가 시스템 시간을 재설정할 수 있나요? Mar 13, 2023 am 10:50 AM

Linux는 시스템 시간을 재설정할 수 있습니다. 1. date 명령을 사용하여 시간을 확인합니다. 2. "yum install ntp" 명령을 사용하여 ntp를 설치합니다. 3. "ntpdate -u ntp.api.bz"를 사용합니다. " 네트워크 시간을 구현하는 명령입니다. 동기화만 하면 됩니다.

PHP에서 시간, 분, 초를 제거하는 방법 PHP에서 시간, 분, 초를 제거하는 방법 Mar 13, 2023 am 11:20 AM

PHP를 사용하여 시간에서 시, 분, 초를 제거하는 방법: 1. PHP 샘플 파일을 만듭니다. 2. strtotime 함수를 사용하여 날짜와 시간을 타임스탬프로 변환합니다. 3. 날짜 함수를 사용하여 날짜 또는 시간 형식을 지정합니다. 시, 분, 초를 제거합니다.

Xiaohongshu에 작품 출판 시간을 설정하는 방법은 무엇입니까? 작품 출판 시기는 정확합니까? Xiaohongshu에 작품 출판 시간을 설정하는 방법은 무엇입니까? 작품 출판 시기는 정확합니까? Mar 24, 2024 pm 01:31 PM

생활과 지식 공유가 가득한 플랫폼 샤오홍슈를 통해 점점 더 많은 창작자들이 자유롭게 자신의 의견을 표현할 수 있게 되었습니다. Xiaohongshu에 대한 관심과 좋아요를 더 많이 얻으려면 콘텐츠의 질뿐만 아니라 작품을 출판하는 시기도 중요합니다. 그렇다면 Xiaohongshu의 작품 출판 시간은 어떻게 설정합니까? 1. 소홍서 작품 출판 시기는 어떻게 정하나요? 1. 사용자의 활동시간을 이해한다. 먼저 Xiaohongshu 사용자의 활동시간을 명확히 할 필요가 있다. 일반적으로 오후 8시부터 10시까지와 주말 오후는 사용자 활동이 많은 시간입니다. 그러나 이 기간은 잠재고객 세그먼트 및 지역과 같은 요인에 따라 달라질 수도 있습니다. 따라서 사용자의 활동 기간을 더 잘 파악하기 위해서는 그룹별 행동 습관에 대한 보다 자세한 분석을 수행하는 것이 좋습니다. 사용자의 삶을 이해함으로써

Go 프로그램을 컴파일하는 데 시간이 더 오래 걸리는 이유는 무엇입니까? Go 프로그램을 컴파일하는 데 시간이 더 오래 걸리는 이유는 무엇입니까? Jun 09, 2023 pm 06:00 PM

최근 몇 년 동안 Go 언어는 점점 더 많은 개발자의 선택이 되었습니다. 그러나 다른 프로그래밍 언어에 비해 Go 언어의 컴파일 속도는 충분히 빠르지 않습니다. 많은 개발자들이 Go 프로그램을 컴파일할 때 다음과 같은 문제에 직면하게 됩니다. Go 프로그램을 컴파일하는 데 시간이 더 오래 걸리는 이유는 무엇입니까? 이 기사에서는 이 문제를 여러 측면에서 살펴볼 것입니다. Go 언어의 컴파일러 아키텍처 Go 언어의 컴파일러 아키텍처는 프론트엔드, 미들 레이어, 백엔드의 3단계 설계를 채택합니다. 프론트 엔드는 소스 코드를 Go 언어의 중간 코드로 변환하는 역할을 담당하며 중간 계층은

Linux 파일 시간 보기 기술에 대한 자세한 설명 Linux 파일 시간 보기 기술에 대한 자세한 설명 Feb 21, 2024 pm 01:15 PM

Linux 파일 시간 보기 기술에 대한 자세한 설명 Linux 시스템에서 파일 시간 정보는 파일 관리 및 변경 사항 추적에 매우 중요합니다. Linux 시스템은 액세스 시간(atime), 수정 시간(mtime), 변경 시간(ctime)이라는 세 가지 주요 시간 속성을 통해 파일 변경 정보를 기록합니다. 이 문서에서는 이 파일 시간 정보를 보고 관리하는 방법을 자세히 설명하고 특정 코드 예제를 제공합니다. 1. ls 명령과 -l 매개변수를 함께 사용하여 파일 목록을 확인하여 파일 시간 정보를 확인합니다.

See all articles