十年网站开发经验 + 多家企业客户 + 靠谱的建站团队
量身定制 + 运营维护+专业推广+无忧售后,网站问题一站解决
编程软件推荐:
目前创新互联建站已为上千余家的企业提供了网站建设、域名、网站空间、网站托管、服务器租用、企业网站设计、临高网站维护等服务,公司将坚持客户导向、应用为本的策略,正道将秉承"和谐、参与、激情"的文化,与客户和合作伙伴齐心协力一起成长,共同发展。
C语言:Vim、C++编译器、Dev-C++、VisualStudio;
Java语言:Eclipse、MyEclipse、NetBeans、IntelliJIDEA;
Python语言:SublimeText、Atom等等
在10gR2中,提供了$ORACLE_HOME/rdbms/admin/sqltrpt.sql脚本,用于抽取占用资源较多的sql,并可以为指定的sql生成执行计划,资源占用较多的sql分为两部分
1) 15 Most expensive SQL in the cursor cache
2) 15 Most expensive SQL in the workload repository
[sql] view plain copy print?
sys@ORCL conn /as sysdba
已连接。
sys@ORCL set linesize 200;
sys@ORCL @?/rdbms/admin/sqltrpt.sql
15 Most expensive SQL in the cursor cache
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
SQL_ID ELAPSED SQL_TEXT_FRAGMENT
------------- ---------- -------------------------------------------------------
b6usrg82hwsa3 52.54 call dbms_stats.gather_database_stats_job_proc ( )
572fbaj0fdw2b 21.16 select output from table(dbms_workload_repository.awr_r
59v4zh1ac3v2a 14.61 DECLARE job BINARY_INTEGER := :job; next_date TIMESTAM
2tr12b1b8uj71 8.69 MERGE /*+ dynamic_sampling(ST 4) dynamic_sampling_est_c
6mcpb06rctk0x 7.58 call dbms_space.auto_space_advisor_job_proc ( )
63kf3an2j0pkc 5.31 insert into sys.wri$_optstat_histgrm_history (obj#,intc
c0j6cx9kzjf7g 4.89 SELECT EXTRACTVALUE(VALUE(T), '/select_list_item/pos')
62yyzw3309d6a 3.89 SELECT VALUE FROM V$SESSION_FIX_CONTROL WHERE BUGNO = :
cvn54b7yz0s8u 3.01 select /*+ index(idl_ub1$ i_idl_ub11) +*/ piece#,length
4y1y43113gv8f 2.72 delete from histgrm$ where obj#=:1 and intcol#=:2 and r
dayq182sk41ks 2.55 insert into wrh$_memory_target_advice (snap_id, dbid,
bm2pwrpcr8ru6 2.53 select sga_size s, sga_size_factor * 100 f,
advr729cu0627 2.51 select * from ( select stat.sql_id as sql_id, sum(elap
bunssq950snhf 2.49 insert into wrh$_sga_target_advice (snap_id, dbid, in
43ruajmwv9fus 2.41 insert into histgrm$(obj#,intcol#,row#,bucket,endpoint,
15 Most expensive SQL in the workload repository
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
SQL_ID ELAPSED SQL_TEXT_FRAGMENT
------------- ---------- --------------------------------------------------------------------------------------------------------------
b6usrg82hwsa3 238.62 call dbms_stats.gather_database_stats_job_proc ( )
59v4zh1ac3v2a 121.83 DECLARE job BINARY_INTEGER := :job; next_date TIMESTAM
db78fxqxwxt7r 81.03 select /*+ rule */ bucket, endpoint, col#, epvalue from
f6cz4n8y72xdc 70.19 SELECT space_usage_kbytes FROM v$sysaux_occupants WH
6mcpb06rctk0x 67.76 call dbms_space.auto_space_advisor_job_proc ( )
5jvf84zg4c49n 67.39 select s.synonym_name as object_name, o.object_type
cvn54b7yz0s8u 59.87 select /*+ index(idl_ub1$ i_idl_ub11) +*/ piece#,length
gqbsq1gpca1gh 52.65 declare logoff_sid pls_integer; logoff_time date :
3ktacv9r56b51 48.01 select owner#,name,namespace,remoteowner,linkname,p_tim
8szmwam7fysa3 43.19 insert into wri$_adv_objspace_trend_data select timepoi
12a2xbmwn5v6z 41.41 select owner, segment_name, blocks from dba_segments wh
c2p32r5mzv8hb 41.28 BEGIN prvt_advisor.delete_expired_tasks; END;
2tr12b1b8uj71 36.90 MERGE /*+ dynamic_sampling(ST 4) dynamic_sampling_est_c
ga6ja2d04ycbm 33.30 DECLARE job BINARY_INTEGER := :job; next_date TIMESTAM
62yyzw3309d6a 33.25 SELECT VALUE FROM V$SESSION_FIX_CONTROL WHERE BUGNO = :
Specify the Sql id
~~~~~~~~~~~~~~~~~~
输入 sqlid 的值: 8szmwam7fysa3
Sql Id specified: 8szmwam7fysa3
Tune the sql
~~~~~~~~~~~~
GENERAL INFORMATION SECTION
-------------------------------------------------------------------------------
Tuning Task Name : 任务_832
Tuning Task Owner : SYS
Workload Type : Single SQL Statement
Scope : COMPREHENSIVE
Time Limit(seconds): 1800
Completion Status : COMPLETED
Started at : 11/19/2013 22:17:00
Completed at : 11/19/2013 22:17:00
-------------------------------------------------------------------------------
Schema Name: SYS
SQL ID : 8szmwam7fysa3
SQL Text : insert into wri$_adv_objspace_trend_data select timepoint,
space_usage, space_alloc, quality from
table(dbms_space.object_growth_trend(:1, :2, :3, :4, NULL, NULL,
NULL, 'FALSE', :5, 'FALSE'))
-------------------------------------------------------------------------------
FINDINGS SECTION (1 finding)
-------------------------------------------------------------------------------
1- Statistics Finding
---------------------
尚未分析表 "SYS"."WRI$_ADV_OBJSPACE_TREND_DATA"。
Recommendation
--------------
- 考虑收集此表的优化程序统计信息。
execute dbms_stats.gather_table_stats(ownname = 'SYS', tabname =
'WRI$_ADV_OBJSPACE_TREND_DATA', estimate_percent =
DBMS_STATS.AUTO_SAMPLE_SIZE, method_opt = 'FOR ALL COLUMNS SIZE
AUTO');
Rationale
---------
为了选择好的执行计划, 优化程序需要此表的最新统计信息。
-------------------------------------------------------------------------------
EXPLAIN PLANS SECTION
-------------------------------------------------------------------------------
1- Original
-----------
Plan hash value: 2976124318
-------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-------------------------------------------------------------------------------------------------------------------
| 0 | INSERT STATEMENT | | 8168 | 32672 | 19 (0)| 00:00:01 |
| 1 | LOAD TABLE CONVENTIONAL | WRI$_ADV_OBJSPACE_TREND_DATA | | | | |
| 2 | COLLECTION ITERATOR PICKLER FETCH| OBJECT_GROWTH_TREND | 8168 | 32672 | 19 (0)| 00:00:01 |
sys@ORCL
目前,在利用hive建设数据仓库的过程中,总会遇见分区分桶的,跟传统的DBMS系统一样,通过表分区能够在特定的区域检索数据,减少扫描成本,在一定程度上提高查询效率。比如我们要收集某个大型网站的日志数据,一个网站每天的日志数据存在同一张表上,由于每天会生成大量的日志,导致数据表的内容巨大,在查询时进行全表扫描耗费的资源非常多。那其实这个情况下,我们可以按照日期对数据表进行分区,不同日期的数据存放在不同的分区,在查询时只要指定分区字段的值就可以直接从该分区查找。在物理上分区表会将数据按照分区键的列值存储在表目录的子目录中,目录名=“分区键=键值”。其中需要注意的是分区键的值不一定要基于表的某一列(字段),它可以指定任意值,只要查询的时候指定相应的分区键来查询即可。
分桶与分区有所不同,它指定分桶表的某一列,让该列数据按照哈希取模的方式随机、均匀地分发到各个桶文件中。因为分桶操作需要根据某一列具体数据来进行哈希取模操作,故指定的分桶列必须基于表中的某一列(字段)。因为分桶改变了数据的存储方式,它会把哈希取模相同或者在某一区间的数据行放在同一个桶文件中。如此一来便可提高查询效率,比如我们要对两张在同一列上进行了分桶操作的表进行JOIN操作的时候,只需要对保存相同列值的桶进行JOIN操作即可。同时分桶也可以提高采样率。
分区是为了对表进行合理的管理以及提高查询效率,Hive可以将表组织成“分区”。一个分区实际上就是表下的一个目录,一个表可以在多个维度上进行分区,分区之间的关系就是目录树的关系。Hive(Inceptor)分区分为静态分区跟动态分区,详细介绍如下:
静态分区在插入或者导入的时候需要指定具体的分区
[if !supportLists]1、 [endif]静态分区创建
需要在PARTITIONED BY后面跟上分区键,类型。例如:
CREATE TABLE p_table1(
id int
,name
string
)
PARTITIONED BY(date_day string)
stored as orc
;
这是一级分区,当然也可以创建多级分区。例如:
CREATE TABLE p_table1(
id int
,name string
)
PARTITIONED BY(date_day string, company
string,emp_no string)
stored as orc
;
下面的实例都是以一级分区为例。
[if !supportLists]2、 [endif]静态分区插入数据
insert overwrite table p_table1 partition(date_day='2019-07-14')
values(1,'lucy');
或者insert overwrite table p_table1 partition(date_day='2019-07-15')
select 2 as id,'lily' as name;
上面两个例子都是覆盖的形式,也就是插入这个分区之前,会将该分区数据删除,再插入新的数据,也可以写成追加的形式:
insert into p_table1
partition(date_day='2019-07-14') values(1,'lucy');
或者insert into e p_table1 partition(date_day='2019-07-15') select 2 as
id,'lily' as name;
[if !supportLists]3、 [endif]静态分区查看分区
查看所有分区show partitions p_table1
结果如下:
date_day=2019-07-14
date_day=2019-07-15
查看某个分区show partitions p_table1 partition(date_day='2019-07-14');
结果如下:
date_day=2019-07-14
[if !supportLists]4、 [endif]静态分区删除分区
删除某个分区alter table p_table1 drop partition(date_day='2019-07-14');
或者删除范围内的分区alter table p_table1 drop partition(date_day='2019-07-14');
1、动态分区创建
创建方式与静态分区表完全一样,一张表可同时被静态和动态分区键分区,只是动态分区键需要放在静态分区建的后面(因为HDFS上的动态分区目录下不能包含静态分区的子目录)。
CREATE TABLE p_table2(
id int
,name string
)
PARTITIONED BY(date_day string,emp_no
string)
stored as orc
;
这是创建了二级分区表。
2、动态分区插入数据
插入数据时需要开启动态数据支持:
set hive.exec.dynamic.partition=true;
set hive.exec.dynamic.partition.mode=nostrict;
插入数据(覆盖)insert overwrite table p_table2 partition(date_day,emp_no)
select 2 as id,'lily' as name,'2019-07-14' as date_day, ‘a’ as emp_no;
分区并没有写死,而是根据查询到的值动态创建的两级分区。
3、动态分区查看分区、删除分区与静态分区操作完全一致不再重述。
分桶字段是表内字段,默认是对分桶的字段进行hash值,然后模总的桶数,得到的值则是分区桶数,主要有以下两点好处:
(1)获得更高的查询处理效率。桶为表加上了额外的结构,Hive 在处理有些查询时能利用这个结构。具体而言,连接两个在(包含连接列的)相同列上划分了桶的表,可以使用 Map 端连接(Map-side join)高效的实现。比如JOIN操作。对于JOIN操作两个表有一个相同的列,如果对这两个表都进行了桶操作。那么将保存相同列值的桶进行JOIN操作就可以,可以大大较少JOIN的数据量。
(2)使取样(sampling)更高效。在处理大规模数据集时,在开发和修改查询的阶段,如果能在数据集的一小部分数据上试运行查询,会带来很多方便。
创建分桶表
先看一下创建分桶表的创建,分桶表的建表有三种方式:直接建表,CREATE TABLE LIKE 和 CREATE TABLE AS SELECT ,单值分区表不能用 CREATETABLE
AS SELECT 建表。这里以直接建表为例:
create table b_table1(id int,name string)
clustered by (id) sorted by(id) into 4 buckets stored as textfile;
使用CLUSTERED BY 子句来指定划分桶所用的列和要划分的桶的个数,当表分区时,每个分区下都会有4个桶。对于map端连接的情况,两个表以相同方式划分桶。处理左边表内某个桶的 mapper知道右边表内相匹配的行在对应的桶内。因此,mapper只需要获取那个桶 (这只是右边表内存储数据的一小部分)即可进行连接。这一优化方法并不一定要求两个表必须桶的个数相同,两个表的桶个数是倍数关系也可以。用HiveQL对两个划分了桶的表进行连接。
桶中的数据可以根据一个或多个列另外进行排序。由于这样对每个桶的连接变成了高效的归并排序(merge-sort), 因此可以进一步提升map端连接的效率。
向分桶表写入数据
如何保证表中的数据都划分成桶了呢?把在Hive外生成的数据加载到划分成桶的表中,当然是可以的。其实让Hive来划分桶更容易。这一操作通常针对已有的表。
Hive并不检查数据文件中的桶是否和表定义中的桶一致(无论是对于桶的数量或用于划分桶的列)。如果两者不匹配,在査询时可能会碰到错误或未定义的结果。因此,建议让Hive来进行划分桶的操作。
要向分桶表中填充成员,需要将 hive.enforce.bucketing 属性设置为 true。这样Hive 就知道用表定义中声明的数量来创建桶。
下面有个未分桶的用户表b_user_test,数据如下:
1 a
2 b
3 c
4 d
5 e
6 f
7 g
插入语句
INSERT OVERWRITE TABLE b_table1 SELECT *
FROM b_user_test;
查看文件结构
dfs -ls/user/hive/warehouse/bucketed_users;
文件结构如下所示:
/user/hive/warehouse/b_table1/000000_0
/user/hive/warehouse/b_table1/000001_0
/user/hive/warehouse/b_table1/000002_0
/user/hive/warehouse/b_table1/000003_0
查看文件000000_0
dfs -cat /user/hive/warehouse/bucketed_users/000000_0;
值为4 d说明文件000000_0存的是对分桶数求余等于0的那部分数据。
对桶中的数据进行采样
对分桶进行查询 tablesample(bucket x out of y on id):
x:表示查询那个桶
y:表示建表指定的桶的总数,如果不是建表时指定的桶的总数,则会重新分桶。
x不能大于y。
取第一个桶的数据:
Sql:SELECT * FROM
b_table1 TABLESAMPLE(BUCKET 2 OUT OF 4 ON id);
结果:
5 e
[if !supportLists]1 [endif]a
当桶数不等于建表指定的桶的总数时
Sql:SELECT * FROM
b_table1 TABLESAMPLE(BUCKET 2 OUT OF 3 ON id);
结果:
4 d
1 a
7 g
由结果可知,进行了重新分桶,分成了三个桶,取出第二个桶的数据,也就是hash值对3求余等于1的那部分数据。
分桶比分区粒度更细,在每个分区了可以将数据进行分桶操作。
1.Mongodb bson文档型数据库,整个数据都存在磁盘中,hbase是列式数据库,集群部署时每个familycolumn保存在单独的hdfs文件中。
2.Mongodb 主键是“_id”,主键上面可以不建索引,记录插入的顺序和存放的顺序一样,hbase的主键就是row key,可以是任意字符串(最大长度是 64KB,实际应用中长度一般为 10-100bytes),在hbase内部,row key保存为字节数组。存储时,数据按照Row key的字典序(byte order)排序存储。设计key时,要充分排序存储这个特性,将经常一起读取的行存储放到一起。
字典序对int排序的结果是1,10,100,11,12,13,14,15,16,17,18,19,2,20,21,…,9,91,92,93,94,95,96,97,98,99。要保持整形的自然序,行键必须用0作左填充。
3.Mongodb支持二级索引,而hbase本身不支持二级索引
4.Mongodb支持集合查找,正则查找,范围查找,支持skip和limit等等,是最像mysql的nosql数据库,而hbase只支持三种查找:通过单个row key访问,通过row key的range,全表扫描
5.mongodb的update是update-in-place,也就是原地更新,除非原地容纳不下更新后的数据记录。而hbase的修改和添加都是同一个命令:put,如果put传入的row key已经存在就更新原记录,实际上hbase内部也不是更新,它只是将这一份数据已不同的版本保存下来而已,hbase默认的保存版本的历史数量是3。
6.mongodb的delete会将该行的数据标示为已删除,因为mongodb在删除记录时并不是真把记录从内存或文件中remove,而是将该删除记录数据置空(写0或特殊数字加以标识)同时将该记录所在地址放到一个list列表“释放列表”中,这样做的好就是就是如果有用户要执行插入记录操作时,mongodb会首先从该“释放列表”中获取size合适的“已删除记录”地址返回,这种方法会提升性能(避免了malloc内存操作),同时mongodb也使用了bucket size数组来定义多个大小size不同的列表,用于将要删除的记录根据其size大小放到合适的“释放列表”中。Hbase的delete是先新建一个tombstonemarkers,然后读的时候会和tombstonemarkers做merge,在 发生major compaction时delete的数据记录才会真真删除。
7.mongodb和hbase都支持mapreduce,不过mongodb的mapreduce支持不够强大,如果没有使用mongodb分片,mapreduce实际上不是并行执行的
8.mongodb支持shard分片,hbase根据row key自动负载均衡,这里shard key和row key的选取尽量用非递增的字段,尽量用分布均衡的字段,因为分片都是根据范围来选择对应的存取server的,如果用递增字段很容易热点server的产生,由于是根据key的范围来自动分片的,如果key分布不均衡就会导致有些key根本就没法切分,从而产生负载不均衡。
9.mongodb的读效率比写高,hbase默认适合写多读少的情况,可以通过hfile.block.cache.size配置,该配置storefile的读缓存占用Heap的大小百分比,0.2表示20%。该值直接影响数据读的性能。如果写比读少很多,开到0.4-0.5也没问题。如果读写较均衡,0.3左右。如果写比读多,果断默认0.2吧。设置这个值的时候,你同时要参考hbase.regionserver.global.memstore.upperLimit,该值是memstore占heap的最大百分比,两个参数一个影响读,一个影响写。如果两值加起来超过80-90%,会有OOM的风险,谨慎设置。
10.hbase采用的LSM思想(Log-Structured Merge-Tree),就是将对数据的更改hold在内存中,达到指定的threadhold后将该批更改merge后批量写入到磁盘,这样将单个写变成了批量写,大大提高了写入速度,不过这样的话读的时候就费劲了,需要merge disk上的数据和memory中的修改数据,这显然降低了读的性能。mongodb采用的是mapfile+Journal思想,如果记录不在内存,先加载到内存,然后在内存中更改后记录日志,然后隔一段时间批量的写入data文件,这样对内存的要求较高,至少需要容纳下热点数据和索引。