澳门新浦京娱乐场网站-www.146.net-新浦京娱乐场官网
做最好的网站

澳门新浦京娱乐场网站:实现数据库表中的流水

原文地址:http://www.maomao365.com/?p=7335

hbase shell命令的使用

再使用hbase 命令之前先检查一下hbase是否运行正常

hadoop@Master:/usr/hbase/bin$ jps
2640 HMaster
27170 NameNode
27533 SecondaryNameNode
3038 Jps
27795 TaskTracker
27351 DataNode
2574 HQuorumPeer
27618 JobTracker
2872 HRegionServer

如果运行不正常的话,关闭hbase后重新启动一下

stop-hbase.sh
start-hbase.sh

 

1.  status命令

hbase(main):008:0> status
1 servers, 0 dead, 3.0000 average load

 

2. version命令

hbase(main):007:0> version
0.94.12, r1524863, Fri Sep 20 00:25:45 UTC 2013

 

3. create 命令
澳门新浦京娱乐场网站:实现数据库表中的流水号,使用sql脚本检测数据表中一列数据是否连续的方法分享。创建一个名为 test澳门新浦京娱乐场网站, 的表,这个表只有一个列为 cf。其中表名、列都要用单引号括起来,并以逗号隔开。

hbase(main):001:0> create 'test', 'cf'
0 row(s) in 10.3830 seconds

4. list 命令
查看当前 HBase 中具有哪些表。

hbase(main):009:0> list
TABLE                                                                           
test                                                                            
1 row(s) in 0.3590 seconds

 

5. put 命令
澳门新浦京娱乐场网站:实现数据库表中的流水号,使用sql脚本检测数据表中一列数据是否连续的方法分享。使用 put 命令向表中插入数据,参数分别为表名、行名、列名和值,其中列名前需要列族最为前缀,时间戳由系统自动生成。
格式: put 表名,行名,列名([列族:列名]),值
例子:
加入一行数据,行名称为“row1”,列族“cf”的列名为”(空字符串)”,值位 value1。
我这里插入3条记录

hbase(main):003:0> put 'test', 'row1', 'cf:a', 'value1'
0 row(s) in 0.2350 seconds

hbase(main):004:0> put 'test', 'row2', 'cf:b', 'value2'
0 row(s) in 0.0350 seconds

hbase(main):005:0> put 'test', 'row3', 'cf:c', 'value3'
0 row(s) in 0.0040 seconds

6. describe 命令
查看表“test”的构造。

hbase(main):010:0> describe 'test'
DESCRIPTION                                          ENABLED                    
 'test', {NAME => 'cf', DATA_BLOCK_ENCODING => 'NONE true                       
 ', BLOOMFILTER => 'NONE', REPLICATION_SCOPE => '0',                            
  VERSIONS => '3', COMPRESSION => 'NONE', MIN_VERSIO                            
 NS => '0', TTL => '2147483647', KEEP_DELETED_CELLS                             
 => 'false', BLOCKSIZE => '65536', IN_MEMORY => 'fal                            
 se', ENCODE_ON_DISK => 'true', BLOCKCACHE => 'true'                            
 }                                                                              
1 row(s) in 1.6630 seconds

7.get 命令
a.查看表“test”中的行“row2”的相关数据。

hbase(main):011:0> get 'test','row2'
COLUMN                CELL                                                      
 cf:b                 timestamp=1381568161926, value=value2                     
1 row(s) in 0.4500 seconds

b.查看表“test”中行“row2”列“cf :b”的值。

hbase(main):012:0> get 'test','row2', 'cf:b'
COLUMN                CELL                                                      
 cf:b                 timestamp=1381568161926, value=value2                     
1 row(s) in 0.3090 seconds

或者

hbase(main):012:0> get 'test', 'row2', {COLUMN=>'cf:b'}
hbase(main):012:0> get 'test', 'row2', {COLUMNS=>'cf:b'}

备注:COLUMN 和 COLUMNS 是不同的,scan 操作中的 COLUMNS 指定的是表的列族, get操作中的 COLUMN 指定的是特定的列,COLUMNS 的值实质上为“列族:列修饰符”。COLUMN 和 COLUMNS 必须为大写。

8. scan 命令
a. 查看表“test”中的所有数据。

hbase(main):006:0> scan 'test'
ROW                   COLUMN CELL                                               
 row1                 column=cf:a, timestamp=1381568140492, value=value1        
 row2                 column=cf:b, timestamp=1381568161926, value=value2        
 row3                 column=cf:c, timestamp=1381568176693, value=value3        
3 row(s) in 0.0770 seconds

注意:
scan 命令可以指定 startrow,stoprow 来 scan 多个 row。
例如:

scan 'user_test',{COLUMNS =>'info:username',LIMIT =>10, STARTROW => 'test', STOPROW=>'test2'}

b.查看表“scores”中列族“course”的所有数据。

hbase(main):012:0> scan  'scores', {COLUMN => 'grad'}
hbase(main):012:0> scan  'scores', {COLUMN=>'course:math'}
hbase(main):012:0> scan  'scores', {COLUMNS => 'course'}
hbase(main):012:0> scan  'scores', {COLUMNS => 'course'}

9.count 命令——统计出表中有多少条记录

hbase(main):013:0> count 'test'
3 row(s) in 1.6530 seconds

10. exists 命令——查看表是否存在

hbase(main):014:0> exists 'test'
Table test does exist                                                           
0 row(s) in 1.1620 seconds

11. incr 命令

给‘test’这个列增加 uid 字段,并使用counter实现递增
连续执行incr以上,COUNTER VALUE 的值会递增,通过get_counter

hbase(main):010:0> incr 'test', 'row2', 'uid', 2
COUNTER VALUE = 2

hbase(main):011:0> incr 'test', 'row2', 'uid', 3
COUNTER VALUE = 5

查看表可以看到:

hbase(main):012:0> scan 'test'
ROW                   COLUMN CELL                                               
 row1                 column=uid:1, timestamp=1381571789416, value=buym:1       
 row2                 column=uid:, timestamp=1381572436088, value=x00x00x00x
                      00x00x00x00x05                                        
 row2                 column=uid:2, timestamp=1381571805008, value=buym:20      
2 row(s) in 0.0790 seconds

12. delete 命令
删除表“test”中行为“row3”, 列族“cf”中的“c”。

hbase(main):015:0> delete 'test','row3','cf:c'
0 row(s) in 0.4640 seconds

 

13. truncate 命令——将表删除后再重新创建

hbase(main):018:0> truncate 'test'
Truncating 'test' table (it may take a while):
 - Disabling table...
 - Dropping table...
 - Creating table...
0 row(s) in 5.6480 seconds

 

14. disbale、drop 命令
通过“disable”和“drop”命令删除“test”表。

hbase(main):001:0> disable 'test'
hbase(main):003:0> drop 'test'
0 row(s) in 3.9310 seconds

澳门新浦京娱乐场网站 1

 

思路:

实现的流水号样式(字符 日期 流水号)如下

SQLSERVER的数据页面结构

 在论坛里经常有人问到SQLSERVER是怎麽存放基础表数据的,既然不想查MSDN,本人就在这里说一下吧

基础表数据都存放在数据页里面,SQLSERVER存储数据都是按照“页”为单位来存放在磁盘的,SQLSERVER从

磁盘读写数据也是按照 “页” 为单位 一页一页地读取到内存,所以有时候如果数据不能塞满整个数据页,那么

这种情况就叫做:page split 页拆分 或者 “碎片”(详细的在文章结尾会跟大家解释一下因为要先了解SQLSERVR

的数据页面结构才能解释清楚) ,SQLSERVER有时候需要读取两页才能把用户需要找的数据读出来

,如果表加了索引的话可以通过重建索引的方法解决,没有建立索引的话就没有办法了

因为建立了索引的表,表里面的数据是放在B树数据结构的索引页,而不是堆数据结构的数据页

 

好像说太多了,现在说一下数据页面是怎样存放数据:

 每一行数据在数据页面里是怎麽存放的?

结构组成:每个SQLSERVER的数据页面大致分成3个部分:页头,页尾偏移量,数据存储 这3个部分

假设现在有一个表,表的结构是:
CREATE TABLE test(
  a INT,
  b INT

他在1:100这个页面上存储数据(1是数据库的数据文件ID 亦即是FILEID,100 是PAGEID 页面编号)。

这个页面结构大致如下图

澳门新浦京娱乐场网站 2

 

在页头部分,会记录页面属性,包括页面编号等,还会记录当前页面空闲部分的起始位置在哪里

这样SQLSERVER在要插入新数据的时候,就能够很快地找到开始插入的位置,而页尾的偏移量

记录了每一条数据行的起始位置。这样SQLSERVER在找每一条记录的时候,就能很快找到不会

把前一条记录和后一条搞混。在图例这一页里现在有两条记录:(1,100)和(2,200)第一条

记录的开始位置是96,第二条记录的开始位置是111,从126开始,是空闲的空间

 

当页面里的数据行发生变化的时候,SQLSERVER不但要去修改数据本身,还要修改这些偏移量的值,

以保证SQLSERVER能够继续准确地管理数据页面里的每一行

 

不知道大家明白不? 该睡觉了,加完班很困哦

2012-12-21补充:

开头说了碎片 页拆分,如果有索引的话也叫“索引碎片”,那么这些碎片是怎麽造成的 以及如何避免和修复呢?

造成的原因很简单:当你删除表里一条记录的时候,SQLSERVER会去找这条记录的所在页面

然后删除,当你删除了之后,那么那个数据页面存放的数据就变成不连续的了,这时候就称为“数据碎片”

就是页面存放的数据不连续,当你删除多条记录,而这些记录都在同一个页面,那么就会造成数据塞不满

整个页面,当你插入一条记录的时候,这条记录是不会插入到你上次删除的那条记录的地方的,如果SQLSERVER

的最后一个数据页面(这些数据页面是用双向链表来链接的)有位置就插入去,没有位置就新开一个页面,然后插入

记录

 

如果存在这些碎片主要两个弊端:

弊端一:SQLSERVER在查找记录的时候要查找多个页面才能找到那条记录(特别使用表扫描执行计划),SQLSERVER按一定顺序

一条一条记录地去找,这样的话本来只需要读取一个页面到内存,SQLSERVER现在需要读取两个页面到内存(特别SQLSERVER

使用表扫描执行计划的时候),会造成内存的使用增大,查找时间增多

 

弊端二:本来使用一个页面可以存放下连续的数据,现在需要两个页面才能存放下这些数据,造成磁盘空间的浪费,占用额外的

磁盘空间

 

如何避免和修复:

最好在表上建立一个聚集索引,然后通过重建索引或者重新组织索引的方式使数据重新按照建立索引的那个字段的顺序重新排序

存储,重建索引会把这些数据页面重新排序把没有“塞满数据”的页面重新“塞满”,并有序排列(更详细的大家可以看一下MSDN)

看一下这些数据是如何按聚集索引的方式来有序存放的

MSDN:聚集索引除了可以提高查询性能之外,还可以按需重新生成或重新组织来控制表碎片。也可以对视图创建聚集索引。

聚集索引基于数据行的键值在表内排序和存储这些数据行。每个表只能有一个聚集索引,因为数据行本身只能按一个顺序存储

只能按一个顺序存储是指:当你建立聚集索引或者主键的时候,你有可能在多个列上建立了聚集索引或者复合主键

SQLSERVER只会按照你创建索引的时候的最左一列的字段来排序,只是一列,不是说先按第一列排序,

再按第二列排序,再按第三列排序。。。。。。

这个有很多人会混淆!!!!!!!!!!!!!!!

 

如果表格上没有聚集索引那么这个问题不能解决,没有聚集索引的表都是堆数据结构的表,就是说数据本身就没有一个排列方式

除非加一个聚集索引,使数据有序排列,非聚集索引也不能解决因为非聚集索引只是在表上加了索引但是数据还是按照“堆”

数据结构来排列的,因为SQLSERVER的页面类型有索引页面,数据页面,LOB页面,行溢出页面,具体大家可以看一下

我之前写的这篇文章:SQLSERVER的表格存储组织结构

 

可以参考的MSDN文章:

聚集索引设计指南

创建聚集索引

创建非聚集索引

非聚集索引设计指南

 

所以很多书上面都说一个数据量比较大的表最好建立一个聚集索引其实也是有道理的

 


2013-8-17 补充:

在正常的数据页上,数据行紧接着页的标头按顺序放置。页的末尾是行偏移量表,对于页中的每一行,每个行偏移表都包含一个条目。

每个条目记录对应行的第一个字节与页首的距离。行偏移表中的条目与页中行的顺序相反

澳门新浦京娱乐场网站 3

 

 

 

 通过一个流水号表,记录当前最大的流水号,以便下次取用。每次取号时,将流水号表更新成大的。

澳门新浦京娱乐场网站 4

摘要:

涉及的表:

流水号.png

 

   流水号表hp_no:  

一般自己在写小demo的时候,都是使用的纯数字自增(1,2,3……)这种。相比而言,流水号形式的看起来更正规,而且可以从流水号中了解数据的添加时间及顺序,当然,是不是看着更有逼格。

   数据表中,有一列是自动流水号,由于各种操作异常原因(或者插入失败),此列数据会变的不连续,下文将讲述使用sql脚本的方式获取数据表中的数据是否连续的方法分享,如下所示:

字段 类型
TYPE_NAME VARCHAR2(100)
START_NO VARCHAR2(100)
CURRENT_NO VARCHAR2(100)

目前我采用的方法是,利用存储过程来实现(可能还有很多方法),因为这种一般是在插入数据的时候使用,所以把插入数据的操作也放在了存储过程。如果目前不知道存储过程这个概念的小白,可以看我这篇的介绍第一次接触存储过程

 

 代码:

<h3>分析</h3>
该字段由三部分组成:QQ字符 201706(年月,即当前日期) 0001(流水号,自动增长)

   实验环境:sqlserver 2008 R2  

1)通过函数得到最大值。 有三个参数,

  1. QQ字符不用管
  2. 201706,当然是先获取到系统当前的时间,然后拿到对应的6位数值
  3. 流水号,为了确保主键不重复,同一时间内,这部分流水号应该是不同的,所以流水号从 0000~9999 ,即同一段时间最多会有一万个不同的流水号。(目前不考虑9999加1之后的情况)

  第一个参数是类型,便于得到不同的流水号。

<h3>实现</h3>
首先建立一个test表,方便讲解

 

  第二个参数是前缀,用于在流水号前边放置特别的字符。

create table test(
     pk_id varchar(12) not null,
     name varchar(10) null
)

例:获取表test中keyId是否为连续的数据

  第三个参数是生成的流水号长度。

实现201706的前一步(拿到当前的年月)

 

 

CONVERT(varchar(8), GETDATE(), 112)  --获取对应格式(20170601)的当前系统时间

实现思路:

澳门新浦京娱乐场网站 5澳门新浦京娱乐场网站 6代码

实现201706,同时把得到的值赋值给一个变量(为了代码看起来清晰)

 

CREATE OR REPLACE FUNCTION Hp_Test_GetNo(
   P_TYPE_NAME   IN   VARCHAR2 DEFAULT '',  --类型 参数1
   P_START_NO    IN   VARCHAR2,  --前缀 参数2
   P_LENGTH      IN   NUMBER    --得到流水号长度 参数3
)
   RETURN VARCHAR2      --返回类型
IS
   V_RESULT       VARCHAR2 (100) := '';   --结果   变量1
   V_CURRENT_NO   VARCHAR2 (100) := '';  --当前值  变量2
   V_NUM          NUMBER         := 0;  --补值    变量3
   V_START_NO   VARCHAR2(100);    --前缀    变量4
   V_ROWID        VARCHAR2 (100);    --要更新行的RowID  变量4
BEGIN
   V_START_NO :=P_START_NO;  --参数值赋给变量

declare @dateStr varchar(6)  --定义变量
----使用substring()方法截取前6位,同时赋值变量
select @dateStr = (select SUBSTRING((Select CONVERT(varchar(8), GETDATE(), 112)),1,6)) 

 1.采用row_number 对表test重新生成流水号

   SELECT COUNT (*)
     INTO V_NUM
     FROM HP_NO
    WHERE TYPE_NAME = P_TYPE_NAME AND START_NO = P_START_NO;    --得到类型与前缀相同值的数量,主要用于判断是否产生过流水号

实现0001的前一步(这里假设表中已经存在一条数据,那么它的4位流水号应该是0000,完整代码部分中会考虑第一条数据的问题。拿到最近生产的4位流水号,新的流水号是在此基础上得到)

 

--判断是否有资料 没有则产生初始值插入库中
   IF V_NUM = 0  --没有记录过时
   THEN
      V_CURRENT_NO := LPAD ('1', P_LENGTH, '0');  --得到P_length长的0001流水号
      V_RESULT := V_CURRENT_NO;  --将前缀与流水号相连起来

----拿到上一个最近生成的pk_id
select top 1 pk_id from table test order by pk_id desc 

 2.采用with as (cte)表达式将重新生成流水号的表放入临时表

      INSERT INTO HP_NO(TYPE_NAME, START_NO, CURRENT_NO)
           VALUES (P_TYPE_NAME, P_START_NO, V_CURRENT_NO);  --将新的最大值记录下来
   ELSE  
      SELECT ROWID, CURRENT_NO   1
      INTO V_ROWID, V_CURRENT_NO
        FROM HP_NO
       WHERE TYPE_NAME = P_TYPE_NAME AND START_NO = P_START_NO; --得到最大值加1

实现0001,这只是开始

 

      V_CURRENT_NO := LPAD (V_CURRENT_NO, P_LENGTH, '0');     
      
      
      UPDATE HP_NO
         SET CURRENT_NO = V_CURRENT_NO
       WHERE ROWID = V_ROWID;    --更新最大值
   END IF;  

declare @maxNo varchar(4)  ----定义变量
----把上诉得到的最近生产的pk_id,通过substring()方法截取最后的4位流水号,然后对其加1
select @maxNo=(Select SUBSTRING( (select top 1 pk_id from test order by pk_id desc),9,4) 1);

 3.对临时表自身进行 左连接(前一行和后一行互补),然后比较行中两张表的keyId 是否相差1,

   IF V_START_NO IS NULL OR V_START_NO='' THEN
      V_RESULT := V_CURRENT_NO;
   ELSE
      V_RESULT :=V_START_NO || V_CURRENT_NO;
   END IF;
   
   RETURN V_RESULT;
END;

虽然新生成了一个流水号,但是不能直接使用,因为如果@maxNo的值不是4位数,那么就会扰乱pk_id的队形,所以需要进行判断

 

使用存储过程调用函数的方法:

if (@maxNo < 10) begin
    set @maxNo = '000'   @maxNo; --如果是1位数的话,需要在前面加3个0,补够4位
end 
else if (@maxNo < 100) begin
    set @maxNo = '00'   @maxNo; --如果是2位数的话,需要在前面加2个0,补够4位
end
else if (@maxNo < 1000) begin
    set @maxNo = '0'   @maxNo; --如果是3位数的话,需要在前面加1个0,补够4位
end

   如果相差1,则代表连续数据行,反之为非连续行数据

澳门新浦京娱乐场网站 7澳门新浦京娱乐场网站 8代码

至此,分割的各个部分都实现了。为了便于插入操作,把所有值结合起来,用一个新的变量来存储

create table test 

(keyId int,info varchar(60))

go

insert into test(keyId,info)values

(1,'maomao365.com'),(2,N'连续数判断'),

(4,N'blog教程'),(5,'maomao'),

(8,'test'),(9,'info')

;

with  tmp as 

 (select  ROW_NUMBER() over (order by keyId asc ) as keyIdNew,

* from test  ) 

select a.keyIdNew,

a.keyId,a.info ,

 case  when ISNULL(a.keyId,0)-1 = b.keyId 

              or b.keyId is null  then '连续'

       else '不连续'

 end as '连续标志'

 from tmp a 

left join tmp b on a.keyIdNew = b.keyIdNew 1

;

go

truncate table test 

drop     table test 

--调用function存储过程
CREATE OR REPLACE PROCEDURE Hp_Pro_GetTestNo
(
      v_FirstLetter in varchar2,
      v_Result out  varchar2
)
   IS
      v_FirstValue varchar2(30);
      v_SystDate varchar2(30);
BEGIN
     select to_char(sysdate,'yyyymm') into v_SystDate from dual;
     v_FirstValue:=(v_FirstLetter || v_SystDate);
     v_Result:=hp_test_getno('HpTest' ,v_FirstValue,4);
END;

declare @result nvarchar(12)--共计12位,前两位为QQ,中间6位是年月,最后4位是流水号
----把之前得到的@dateStr和maxNo加上,QQ字符直接加上即可
select @result=(Select 'QQ'   @dateStr   @maxNo);

 澳门新浦京娱乐场网站 9

结果:

最后,把需要插入表中的数据作为参数传递到存储过程中,在存储过程中执行插入操作

 

   调用存储过程Hp_Pro_GetTestNo('hp',4);

@name -- 需要插入test表中的值
insert into test(pk_id,name) values(@result,@name)

  结果为:hp2010020001

这就是完整的过程,在执行插入数据的操作时,把除了pk_id之外的字段当做参数传入到存储过程中,在存储过程中执行insert操作即可

 

完整的存储过程代码如下

其它思考

USE [Test] ----Test是test表所在的数据库名
GO
/****** Object:  StoredProcedure [dbo].[AddData]    Script Date: 06/01/2017 18:51:04 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE [dbo].[AddData]  
    @name varchar(10)  ----参数,用于接收传入的name值
AS
BEGIN
    -- SET NOCOUNT ON added to prevent extra result sets from
    -- interfering with SELECT statements.
    SET NOCOUNT ON;

    declare @dateStr varchar(6),  ----定义变量,用于存储6位数的时间
    @maxNo varchar(4), ----定义变量,用于存储4位流水号
    @result varchar(12) -----定义变量,用于存储新生成的pk_id

    ----获取到系统当前时间,并截取符合条件的6位,同时赋值给@dateStr
    select @dateStr = (select SUBSTRING((Select CONVERT(varchar(8), GETDATE(), 112)),1,6))

    ----先判断是否第一次向test表中插入数据(即当前表中是否存在数据)
    if exists (select * from test) begin
        ----获取数据表中最近产生的一个pk_id,并截取最后4位流水号,对4位流水号进行加1,最后赋值给@maxNo
        select @maxNo=(Select SUBSTRING( (select top 1 pk_id from test order by pk_id desc),9,4) 1);

        ----对上诉的@maxNo做判断,确保流水号一定是4位,不够的在前面补0
        if (@maxNo < 10) begin
            set @maxNo = '000'   @maxNo; --如果是1位数的话,需要在前面加3个0,补够4位
        end 
        else if (@maxNo < 100) begin
            set @maxNo = '00'   @maxNo; --如果是2位数的话,需要在前面加2个0,补够4位
        end
        else if (@maxNo < 1000) begin
            set @maxNo = '0'   @maxNo; --如果是3位数的话,需要在前面加1个0,补够4位
        end

        ----将上诉结果合成一个新的pk_id
        select @result=(Select 'QQ'   @dateStr   @maxNo)
    end 
    else
       ----如实当前插入的数据时第一条数据,那么直接把4位流水号设为0000
       select @result = 'QQ'   @dateStr   '0000'

    ----将数据插入到test表中
    insert into test(pk_id,name) values(@result,@name);
END

一、新增时无须显示流水号,如得到得到连续流水号

 方法:

  采用流水号子表,此表用于保存没有用过的流水号。当用户取号时,首选判断子表是否含有流水号,当有时,取出一个,并删除此个(防止别另外用户取用);否则调用主表得到新流水号。

当插入失败则将当前流水号保存到流水号子表中,供下次取用。

当删除时,将当前流水号保存到流水号子表中,供下次取用。

二、新增时须显示流水号,如得到得到连续流水号

方法:

  采用流水号子表,此表用于保存没有用过的流水号。当用户取号时,首选判断子表是否含有流水号,当有时,取出一个,并删除此个(防止别另外用户取用);否则调用 主表得到新流水号。

当用户不保存或插入失败则将当前流水号保存到流水号子表中,供下次取用。

当删除时,将当前流水号保存到流水号子表中,供 下次取用。

 

其它思考的代码我没有写,有兴趣的朋友可以自己写。

 

 

 

本文由澳门新浦京娱乐场网站发布于数据库,转载请注明出处:澳门新浦京娱乐场网站:实现数据库表中的流水