通过分区键值发现性能问题

在很多应用中如果数据量少有规模,都会有大量的分区表存在,使用比较多的是range partition.
一般的range partition都一时间为键值,或者根据业务绑定的关键id值。
虽然已经做了一些大数据量的数据迁移,但是不管是按照分区抽取,还是根据数据条数抽取,发现有一个表比较奇怪,一个100G左右的分区表,80%以上的数据都分布在一个分区里面,而这个大分区表却有180多个分区表。
如下所示,对于表charge,如果分区的大小在200M以内,就标记为1,如果大于200M,则按照200M为单位进行统计,可以看到,如下的分区  P120_C10占用了大量的空间,其他的分区却小的可怜。很明显从业务规划的角度存在一定的问题。
CHARGE                               P120_C100                             1                    
CHARGE                               P120_C10                            438                    
CHARGE                               P120_C20                              1                    
CHARGE                               P120_C30                              1                    
CHARGE                               P120_C40                              1                    
CHARGE                               P120_C50                              1                    
CHARGE                               P120_C60                              1                    
CHARGE                               P120_C70                              1                    
CHARGE                               P120_C80                              1                    
CHARGE                               P120_C90                              1                    
CHARGE                               P25_C100                              1                    
CHARGE                               P25_C10                               2                    
CHARGE                               P25_C20                               1                    
CHARGE                               P25_C30                               1                    
CHARGE                               P25_C40                               1                    
CHARGE                               P25_C50                               1                    
CHARGE                               P25_C60                               1                    
CHARGE                               P25_C70                               1                    
CHARGE                               P25_C80                               1                    
CHARGE                               P25_C90                               1                    
CHARGE                               P26_C100                              1                    
CHARGE                               P26_C10                               1                    
CHARGE                               P26_C20                               1                    
CHARGE                               P26_C30                               1                    
CHARGE                               P26_C40                               1                    
CHARGE                               P26_C50                               1                    
CHARGE                               P26_C60                               1                    
CHARGE                               P26_C70                               1                    
CHARGE                               P26_C80                               1                    
CHARGE                               P26_C90                               1                    
CHARGE                               P27_C100                              1                    
CHARGE                               P27_C10                               1                    
CHARGE                               P27_C20                               1                    
CHARGE                               P27_C30                               1                    
CHARGE                               P27_C40                               1                    
CHARGE                               P27_C50                               1   

带着这个疑问,和对应的开发人员进行了沟通,因为这个表已经使用很长时间了,他们想让我们提供一些关键的信息,比如分区的逻辑等,简单抽取了一些信息如下,
对于最大的分区P120_C10来说,High_value是120,10 直接看也看不出来什么问题。

PARTITION_NAME            HIGH_VALUE      TS_NAME     INI_TRANS LOGGING COMPRESS GLO LAST_ANAL
------------------------- --------------- ---------- ---------- ------- -------- --- ---------
.......
P41_C90                   41, 90          DATAH01             8 NO      DISABLED YES 15-AUG-14
P41_C100                  41, 100         DATAH01             8 NO      DISABLED YES 15-AUG-14
P120_C10                  120, 10         DATAH01             8 NO      DISABLED YES 15-AUG-14
P120_C20                  120, 20         DATAH01             8 NO      DISABLED YES 12-AUG-14
P120_C30                  120, 30         DATAH01             8 NO      DISABLED YES 12-AUG-14
P120_C40                  120, 40         DATAH01             8 NO      DISABLED YES 12-AUG-14
P120_C50                  120, 50         DATAH01             8 NO      DISABLED YES 12-AUG-14
P120_C60                  120, 60         DATAH01             8 NO      DISABLED YES 12-AUG-14
P120_C70                  120, 70         DATAH01             8 NO      DISABLED YES 12-AUG-14
P120_C80                  120, 80         DATAH01             8 NO      DISABLED YES 12-AUG-14
P120_C90                  120, 90         DATAH01             8 NO      DISABLED YES 12-AUG-14
P120_C100                 120, 100        DATAH01             8 NO      DISABLED YES 12-AUG-14

根据最初的需求,是希望对于键值#1P120_C10 这个分区里面。
根据他们的期望,我对分区的数据进行了简单的分析,发现对于分区的键值在满足第一个分区的条件下,对于第二个键值的条件就直接忽略了。
select period_key,CUSTOMER_KEY from charge partition(P120_C10) group by  period_key,CUSTOMER_KEY order by period_key,customer_key
SQL> /
        42            0
        42            1
        42            2
 ....
        42           14
        42           15
        42           16
        42           17
...
        42           99
        43            0
 ...
        44           99
        45            0
        45            1
        45            2
        45            3
        45            4
...
        45           98
        45           99
        46            0
        46            1
        46            2
        46            3
        46            4
        46            5
        46            6
        46            7
        46            8
        46            9
        46           10
        46           11
        46           12
...
        57           88
        57           89
        57           90
        57           91
        57           92
        57           93
        57           94
        57           95
        57           96
        57           97
        57           98
        57           99

如果这样看,似乎有些不太合理了,是什么原因导致这些数据进入p120_c10了呢。
来做个简单的测试模拟一下,发现对于这个多键值的分区表,分区的情况和单键值还是有很大的差别,比较容易混淆和误导。当第一个键值的条件满足时,就忽略了第二个键值的条件,(比如(55,70),55已经小于第一个键值了,就直接插入p120_c10了,忽略了后面的一个条件)
如果键值等于120的时候,就开始校验第二个条件了(比如(120,5), (120,15)都校验了后面的键值,数据分别进入了p120_c10,p120_c20这两个分区)
如果键值大于120的时候,如果没有默认的分区,就直接报错了,因为oracle根据这种匹配还找不到对应的分区。

create
table test (period_key number,customer_key number)

partition
by range(period_key,customer_key)

(

partition
p120_c10 values less than (120,10),

partition
p120_c20 values less than (120,20),

partition
p120_c30 values less than (120,30)

);

  

SQL>
insert into test values(57,99);

1 row
created.

SQL>
insert into test values(57,150);

1 row
created.

SQL>
insert into test values(120,5);

1 row
created.

SQL>
insert into test values(119,50);

1 row
created.

SQL>
insert into test values(120,5);

1 row
created.

SQL>
insert into test values(120,15);

1 row
created.

SQL>
insert into test values(120,25);

1 row
created.

SQL>
insert into test values(120,30);

insert
into test values(120,30)

           
*

ERROR
at line 1:

ORA-14400:
inserted partition key does not map to any partition

SQL>
insert into test values(121,1);

insert
into test values(121,1)

           
*

ERROR
at line 1:

ORA-14400:
inserted partition key does not map to any partition

 

SQL>
select *from test partition(p120_c10);

PERIOD_KEY
CUSTOMER_KEY

----------
------------

       
57          
99

       
57          150

      
120            5

      
119           50

      
120            5

 

SQL>
select *from test partition(p120_c20);

PERIOD_KEY
CUSTOMER_KEY

----------
------------

      
120           15

 

SQL>
select *from test partition(p120_c30);

PERIOD_KEY
CUSTOMER_KEY

----------
------------

      
120           25

 

对于这个问题,只能根据业务的角度进行重新规划来把数据进一步balance了。

时间: 2024-09-21 09:16:51

通过分区键值发现性能问题的相关文章

第六章——根据执行计划优化性能(3)——键值查找

原文:第六章--根据执行计划优化性能(3)--键值查找 前言:         本文为本系列最后一篇,介绍键值查找的相关知识.         键值查找是具有聚集索引的表上的一个书签查找,键值查找用于SQLServer查询一些非键值列的数据.使用非聚集索引的查询不会有键值查找,但是所有键值查找会伴随非聚集索引出现.这里特别提醒的是键值查找总是伴有嵌套循环关联.   准备工作:   下面将创建一个表,通过执行计划看看键值查找的不同效果.为了产生键值查找,需要两件事情: 1.  聚集索引 2.  非

非分区键的GLOBAL分区索引键值更新会造成麻烦吗?

我们都知道如果想修改分区表的分区键的值如果跨越了分区,那么必须加入ENABLE ROW MOVEMENT 进行,因为此时可能的ROWID会出现变动, 关于ROWID 如下: Object ID (4 bytes) + DBA (4 bytes) + Row (2 bytes) 其中DBA包含了BLOCK地址和DATAFILE地址,如果UPDATE分区键的记录,可能的DATAFILE和BLOCK 都需要变动,所以要开启ENABLE ROW MOVEMENT. 而修改分区索引的键值在多个分区中移动为

Spark学习之键值对(pair RDD)操作(3)

Spark学习之键值对(pair RDD)操作(3) 1. 我们通常从一个RDD中提取某些字段(如代表事件时间.用户ID或者其他标识符的字段),并使用这些字段为pair RDD操作中的键. 2. 创建pair RDD 1)读取本身就是键值对的数据 2)一个普通的RDD通过map()转为pair RDD,传递的函数需要返回键值对. Python中使用第一个单词作为键创建出一个pair RDD pairs = lines.amp(lambda x: (x.split(" ")[0],x))

Python+MongoDB自增键值的简单实现_python

背景 最近在写一个测试工具箱,里面有一个bug记录系统,因为后台我是用Django和MongoDB来实现的,就遇到了一个问题,要如何实现一个自增的字段. 传统的关系型数据库要实现起来是非常容易,只要直接设置一个自增字段就行了,插入数据时不用管这个键值,只管自己处理的数据就行了,会自动实现自增的功能,但是非关系型数据库好像没有这个功能(或者我不知道).百度之后发现都是MongoDB的设置方法,并不是我想要的. 解决思路 百度没有找到好的思路,那就只能自己解决了,我的想法很简单,字段不会自增,那么就

LightCloud:分布式键-值数据库

Plurk.com在今年2月28日开源了LightCloud这个分布式的键-值数据库,根据 官方网站的信息,有以下特性 基于Tokyo Tyrant(这个项目貌似又是另一个名叫Tokyo Cabinet的数据库系 统的网络接口).Tokyo Tyrant是最快的键-值数据库之一,并且已经开发了好几 年并且在n个网站中被应用. 性能非常好(可以和memcached进行对比) 在很少的服务器上面可以存储百万级的数据量 简单的通过添加节点来扩展 节点可以通过master-master复制来进行备份.很

解析一个通过添加本地分区索引提高SQL性能的案例

今天接到同事求助,说有一个select query,在Oracle上要跑一分多钟,他希望能在5s内出结果,以下就是解决这个问题的方法,需要的朋友可以参考下   该sql如下: 复制代码 代码如下: Select  /*+ parallel(src, 8) */ distinct   src.systemname as systemname   ,  src.databasename as databasename   ,  src.tablename as tablename   ,  src.

键值-std::map和stdext::hash_map效率问题

问题描述 std::map和stdext::hash_map效率问题 近期,接到一个项目,由于需要在程序运行中解析一部分数据,且该部分数据需要向后提供. 所以前同事在设计时使用了stdext::hash~map. 近期在优化该程序,需要将处理能力提高100%,我从IO,队列锁等方面改了一大通,现在效率才提高50%. 所以想问下经验较多的人,map和hash~map效率到底差距有多少(结合我的使用场景). 1.每个map(hash~map)最多只有100个数据,键值为string std::map

MyBatis获取自增长主键值的两种方式及源码浅析

昨天在做项目的时候遇到了一个坑,没错,就是获取MyBatis自增长主键值的坑.因为之前一直用ibatis,所以惯性的用了ibatis的写法,结果返回的值一直是1(受影响的行数).于是去翻了翻MyBatis的源码,发现它把主键值放到了参数对象上,获取主键值需要用参数对象去get主键值.真是坑.我先把解决办法放出来,然后再接着分析MyBatis的源码是怎么做的. 环境: 数据库MySql.User表,主键设置为自增长. CREATE TABLE `user` ( `id` INT(11) NOT N

键值数据库 IonDB

IonDB 详细介绍 IonDB 专为 Arduino 和 IoT 提供开箱即用的,基于磁盘的快速存储功能,为受限系统提供键值存储功能,速度非常快,可以充分提升 Arduino 的性能. 这个项目是英国哥伦比亚的奥肯那根大学 Ramon Lawrence 博士指导项目的一部分,由 Lawrence 博士的分布式数据实验室支持.还有另外一个类似的项目,也是专为嵌入式设备和传感器节点设计的关系型数据库 LittleD. 一般情况下,IonDB 支持: 存储一个键的任意值 重复键支持 范围和等值查询