-
야호!! 드디어 삭제다!
2018/08/10 - [2018년 하반기/HBASE] - 3장 클라이언트 API : 기본기능 - Put 메서드
2018/08/17 - [2018년 하반기/HBASE] - 3장 클라이언트 API : 기본기능 - Get 메서드
CRUD(Create,Read,Update,Delete) 기능
출처: http://weejw.tistory.com/category/2018년 하반기/HBASE# [위지원의 블로그]CRUD(Create,Read,Update,Delete) 기능
출처: http://weejw.tistory.com/category/2018년 하반기/HBASE# [위지원의 블로그]CRUD(Create,Read,Update,Delete) 기능
2.Get 메서드
출처: http://weejw.tistory.com/category/2018년 하반기/HBASE [위지원의 블로그]CRUD(Create,Read,Update,Delete) 기능
출처: http://weejw.tistory.com/category/2018년 하반기/HBASE# [위지원의 블로그]CRUD(Create,Read,Update,Delete) 기능
출처: http://weejw.tistory.com/category/2018년 하반기/HBASE# [위지원의 블로그]CRUD(Create,Read,Update,Delete) 기능
2.Get 메서드
출처: http://weejw.tistory.com/category/2018년 하반기/HBASE [위지원의 블로그]CRUD(Create,Read,Update,Delete) 기능
3.Delete 메서드
Delete 라는 클래스를 이용해서 삭제를 수행할 수 있다. Delete 객체를 생성해서 테이블의 delete 메서드로 넘겨줄 수 있다.
delete 객체를 생성하는 방법은 역시 여러가지가 있지만, 그 중에서 몇개만 살펴보자면 가장 기본인 row만 넘겨주는 경우와 timestamp까지 넘겨주는 경우가 있다.
Delete class의 다음 메서드를 사용하면 row에서 삭제하고자 하는 데이터의 범위를 좁힐 수 있다.
Table table = connection.getTable(TableName.valueOf("testtable"));
Delete delete = new Delete(Bytes.toBytes("row1")); //특정 row를 지정한다.
delete.setTimestamp(1); // row 삭제를 위한 TimeStemp를 지정한다.
delete.addColumn(Bytes.toBytes("colfam1"), Bytes.toBytes("qual1")); //컬럼하나의 모든 version을 삭제한다.
delete.addColumn(Bytes.toBytes("colfam1"), Bytes.toBytes("qual2"), 3); // 특정 version과 그 이전버전을 모두 삭제한다.
//변경되었다. version이 아니라 TimeStemp를 넘겨줘야한다(API참조)
delete.addFamily(Bytes.toBytes("colfam1")); //Family를 모두 삭제한다.
delete.addFamily(Bytes.toBytes("colfam1"), 3); //특정 version과 그 이전 버전을 모두 삭제한다.
table.delete(delete);위에 다양한 방법중에 특정 퀄리파이어를 삭제한 장면이다.이것은 컬럼 패밀리를 삭제해본 모습이다.version삭제가 안된다.. 한참을 고민한끝에 그것은 바로!! timestamp 값을 지정해서 값을 PUT! 해줘야한다는 것이였다..^^;; 지난번 배운 Put 메서드에서 보면 long ts로 timestemp를 지정해서 생성할 수 있었다. 해보자.(책을 너무 대충읽오 있나보다)일반으로 지정된 시간에 대해서 삭제하려고 하면 자바 API로 하면 아래와 같이 오류가 뜬다. 분명 아규먼트 타입상 Long의 자리인데..음..,,Delete delete = new Delete(Bytes.toBytes("row1"));
delete.addColumns(Bytes.toBytes("colfam1"), Bytes.toBytes("qual2"), 1534501337711);같은 코드를 shell에서 외쳤을때는 전혀 문제가 없다..ㅠ_ㅠ 왜일까?Delete 리스트
Delete 인스턴스의 리스트를 생성해서 한번에 삭제한다. 위에서 소개할때 두번째에 있던 친구이다.
이번에는 바~로 코딩에 들어가보겠다.!!
아래 코드를 이용하여서 비어있는 테이블에 데이터를 삽입해주자.
Put put = new Put(Bytes.toBytes("row1"));
put.addColumn(Bytes.toBytes("colfam1"),Bytes.toBytes("qual1"),1,Bytes.toBytes("val1"));
put.addColumn(Bytes.toBytes("colfam1"),Bytes.toBytes("qual1"),2,Bytes.toBytes("val2"));
put.addColumn(Bytes.toBytes("colfam1"),Bytes.toBytes("qual2"),3,Bytes.toBytes("val3"));
put.addColumn(Bytes.toBytes("colfam2"),Bytes.toBytes("qual2"),4,Bytes.toBytes("val4"));
put.addColumn(Bytes.toBytes("colfam2"),Bytes.toBytes("qual3"),5,Bytes.toBytes("val5"));
put.addColumn(Bytes.toBytes("colfam2"),Bytes.toBytes("qual3"),6,Bytes.toBytes("val6"));
Put put2 = new Put(Bytes.toBytes("row2"));
put2.addColumn(Bytes.toBytes("colfam1"),Bytes.toBytes("qual1"),1,Bytes.toBytes("val1"));
put2.addColumn(Bytes.toBytes("colfam1"),Bytes.toBytes("qual1"),2,Bytes.toBytes("val2"));
put2.addColumn(Bytes.toBytes("colfam1"),Bytes.toBytes("qual2"),3,Bytes.toBytes("val3"));
put2.addColumn(Bytes.toBytes("colfam2"),Bytes.toBytes("qual2"),4,Bytes.toBytes("val4"));
put2.addColumn(Bytes.toBytes("colfam2"),Bytes.toBytes("qual3"),5,Bytes.toBytes("val5"));
put2.addColumn(Bytes.toBytes("colfam2"),Bytes.toBytes("qual3"),6,Bytes.toBytes("val6"));
Put put3 = new Put(Bytes.toBytes("row3"));
put3.addColumn(Bytes.toBytes("colfam1"),Bytes.toBytes("qual1"),1,Bytes.toBytes("val1"));
put3.addColumn(Bytes.toBytes("colfam1"),Bytes.toBytes("qual2"),2,Bytes.toBytes("val2"));
put3.addColumn(Bytes.toBytes("colfam1"),Bytes.toBytes("qual2"),3,Bytes.toBytes("val3"));
put3.addColumn(Bytes.toBytes("colfam2"),Bytes.toBytes("qual2"),4,Bytes.toBytes("val4"));
put3.addColumn(Bytes.toBytes("colfam2"),Bytes.toBytes("qual3"),5,Bytes.toBytes("val5"));
put3.addColumn(Bytes.toBytes("colfam2"),Bytes.toBytes("qual3"),6,Bytes.toBytes("val6"));
Table table = connection.getTable(TableName.valueOf("testtable"));
table.put(put);
table.put(put2);
table.put(put3);hbase(main):006:0> scan 'testtable',{VERSIONS=>5}
ROW COLUMN+CELL
row1 column=colfam1:qual1, timestamp=2, value=val2
row1 column=colfam1:qual1, timestamp=1, value=val1
row1 column=colfam1:qual2, timestamp=3, value=val3
row1 column=colfam2:qual2, timestamp=4, value=val4
row1 column=colfam2:qual3, timestamp=6, value=val6
row1 column=colfam2:qual3, timestamp=5, value=val5
row2 column=colfam1:qual1, timestamp=2, value=val2
row2 column=colfam1:qual1, timestamp=1, value=val1
row2 column=colfam1:qual2, timestamp=3, value=val3
row2 column=colfam2:qual2, timestamp=4, value=val4
row2 column=colfam2:qual3, timestamp=6, value=val6
row2 column=colfam2:qual3, timestamp=5, value=val5
row3 column=colfam1:qual1, timestamp=1, value=val1
row3 column=colfam1:qual2, timestamp=3, value=val3
row3 column=colfam1:qual2, timestamp=2, value=val2
row3 column=colfam2:qual2, timestamp=4, value=val4
row3 column=colfam2:qual3, timestamp=6, value=val6
row3 column=colfam2:qual3, timestamp=5, value=val5
3 row(s)
Took 0.1618 seconds그리고 나서 Delete List를 생성하고 그안에 delete 객체를 생성해서 add()한 뒤 삭제해주자.
List<Delete> deletes = new ArrayList<Delete>();
Delete delete1 = new Delete(Bytes.toBytes("row1"));
delete1.setTimestamp(4); //row1에서 timestemp가 4인것과 그것보다 낮은것들을 삭제한다.
deletes.add(delete1);
Delete delete2 = new Delete(Bytes.toBytes("row2"));
delete2.addColumn(Bytes.toBytes("colfam1"), Bytes.toBytes("qual1")); //row2에서 qual1의 최신버전 1개 삭제
delete2.addColumns(Bytes.toBytes("colfam2"), Bytes.toBytes("qual3"), 5); //qual3중에 timestemp가 5인것
deletes.add(delete2);
Delete delete3 = new Delete(Bytes.toBytes("row3"));
delete3.addFamily(Bytes.toBytes("colfam1")); //row3의 colfam1을 삭제한다.
delete3.addFamily(Bytes.toBytes("colfam2"), 3); //row3의 colfam2중에서 timestemp가 3인것과 그보다 낮은 것을 삭제한다.
deletes.add(delete3);
table.delete(deletes);hbase(main):007:0> scan 'testtable',{VERSIONS=>5}
ROW COLUMN+CELL
row1 column=colfam2:qual3, timestamp=6, value=val6
row1 column=colfam2:qual3, timestamp=5, value=val5
row2 column=colfam1:qual1, timestamp=1, value=val1
row2 column=colfam1:qual2, timestamp=3, value=val3
row2 column=colfam2:qual2, timestamp=4, value=val4
row2 column=colfam2:qual3, timestamp=6, value=val6
row3 column=colfam2:qual2, timestamp=4, value=val4
row3 column=colfam2:qual3, timestamp=6, value=val6
row3 column=colfam2:qual3, timestamp=5, value=val5
3 row(s)
Took 0.0964 seconds위에 메소드에다가 버그를 하나 심어주고 확인을 해보자.
Delete delete4 = new Delete(Bytes.toBytes("row2"));
delete4.addColumn(Bytes.toBytes("BOGUS"),Bytes.toBytes("qual1"));
deletes.add(delete4);
try {
table.delete(deletes);
} catch (Exception e) {
System.err.println("Error: " + e);
}
table.close();
System.out.println("Deletes length: " + deletes.size()); //리스트에 남아있는 친구가 있는지 확인을 해보자
for (Delete delete : deletes) {
System.out.println(delete);
}그럼 아래와 같이 굉장히 길게 에러가 출력되는데 중요한건 가장 마지막에 있는 단 하나! 리스트에는 delete 객체가 단하나! 남아있다.
Error: org.apache.hadoop.hbase.client.RetriesExhaustedWithDetailsException: Failed 1 action:
org.apache.hadoop.hbase.regionserver.NoSuchColumnFamilyException: Column family BOGUS does not exist in region testtable,,1534504182114.f9ed523be3cbf3a9902c1b7718d08937. in table 'testtable', {NAME => 'colfam1', VERSIONS => '10', EVICT_BLOCKS_ON_CLOSE => 'false', NEW_VERSION_BEHAVIOR => 'false', KEEP_DELETED_CELLS => 'FALSE', CACHE_DATA_ON_WRITE => 'false', DATA_BLOCK_ENCODING => 'NONE', TTL => 'FOREVER', MIN_VERSIONS => '0', REPLICATION_SCOPE => '0', BLOOMFILTER => 'ROW', CACHE_INDEX_ON_WRITE => 'false', IN_MEMORY => 'false', CACHE_BLOOMS_ON_WRITE => 'false', PREFETCH_BLOCKS_ON_OPEN => 'false', COMPRESSION => 'NONE', BLOCKCACHE => 'true', BLOCKSIZE => '65536'}, {NAME => 'colfam2', VERSIONS => '10', EVICT_BLOCKS_ON_CLOSE => 'false', NEW_VERSION_BEHAVIOR => 'false', KEEP_DELETED_CELLS => 'FALSE', CACHE_DATA_ON_WRITE => 'false', DATA_BLOCK_ENCODING => 'NONE', TTL => 'FOREVER', MIN_VERSIONS => '0', REPLICATION_SCOPE => '0', BLOOMFILTER => 'ROW', CACHE_INDEX_ON_WRITE => 'false', IN_MEMORY => 'false', CACHE_BLOOMS_ON_WRITE => 'false', PREFETCH_BLOCKS_ON_OPEN => 'false', COMPRESSION => 'NONE', BLOCKCACHE => 'true', BLOCKSIZE => '65536'}
at org.apache.hadoop.hbase.regionserver.RSRpcServices.doBatchOp(RSRpcServices.java:1038)
at org.apache.hadoop.hbase.regionserver.RSRpcServices.doNonAtomicBatchOp(RSRpcServices.java:961)
at org.apache.hadoop.hbase.regionserver.RSRpcServices.doNonAtomicRegionMutation(RSRpcServices.java:924)
at org.apache.hadoop.hbase.regionserver.RSRpcServices.multi(RSRpcServices.java:2673)
at org.apache.hadoop.hbase.shaded.protobuf.generated.ClientProtos$ClientService$2.callBlockingMethod(ClientProtos.java:42014)
at org.apache.hadoop.hbase.ipc.RpcServer.call(RpcServer.java:409)
at org.apache.hadoop.hbase.ipc.CallRunner.run(CallRunner.java:130)
at org.apache.hadoop.hbase.ipc.RpcExecutor$Handler.run(RpcExecutor.java:324)
at org.apache.hadoop.hbase.ipc.RpcExecutor$Handler.run(RpcExecutor.java:304)
: 1 time, servers with issues: netdb.slave2.com,16020,1534483987538
Deletes length: 1
{"totalColumns":1,"row":"row2","families":{"BOGUS":[{"qualifier":"qual1","vlen":0,"tag":[],"timestamp":9223372036854775807}]},"ts":9223372036854775807}원자적 '확인 후 삭제' 연산
힘들어죽겠다.자 다음은 원자적 확인후 삭제이다. Put에서 한것처럼 확인을 먼저한다음에 라는 전제 조건이 붙은 것 뿐이다.
table class의 API를 확인하니 오호호호호 Deprecated... checkAndMutate를 대신 애용해달라는 말이 보인다. 일단 checkAndDelete예제부터 해보자.
Put put = new Put(Bytes.toBytes("row1"));
put.addColumn(Bytes.toBytes("colfam1"),Bytes.toBytes("qual1"),1,Bytes.toBytes("val1"));
put.addColumn(Bytes.toBytes("colfam1"),Bytes.toBytes("qual2"),2,Bytes.toBytes("val2"));
put.addColumn(Bytes.toBytes("colfam1"),Bytes.toBytes("qual3"),3,Bytes.toBytes("val3"));put.addColumn(Bytes.toBytes("colfam2"),Bytes.toBytes("qual1"),1,Bytes.toBytes("val1"));
put.addColumn(Bytes.toBytes("colfam2"),Bytes.toBytes("qual2"),2,Bytes.toBytes("val2"));
put.addColumn(Bytes.toBytes("colfam2"),Bytes.toBytes("qual3"),3,Bytes.toBytes("val3"));
table.put(put); //새로운 값들을 삽입하고
Delete delete1 = new Delete(Bytes.toBytes("row1"));
delete1.addColumns(Bytes.toBytes("colfam1"), Bytes.toBytes("qual3"));
boolean res1 = table.checkAndDelete(Bytes.toBytes("row1"),
Bytes.toBytes("colfam2"), Bytes.toBytes("qual3"), null, delete1); //앞에 조건이 맞으면(null이라는) 마지막 delete1 연산을 수행한다.
System.out.println("Delete 1 successful: " + res1);
Delete delete2 = new Delete(Bytes.toBytes("row1"));
delete2.addColumns(Bytes.toBytes("colfam2"), Bytes.toBytes("qual3")); //삭제한다.
table.delete(delete2);
boolean res2 = table.checkAndDelete(Bytes.toBytes("row1"),
Bytes.toBytes("colfam2"), Bytes.toBytes("qual3"), null, delete1); //바로 위에서 삭제했기때문에 value부분에 전달한 파라미터 null과 조건이 맞기때문에 이번에는 true가 출력된다.* delete연산은 맞는게 없으면 아무것도 수행하지 않는다.
System.out.println("Delete 2 successful: " + res2);
Delete delete3 = new Delete(Bytes.toBytes("row2"));
delete3.addFamily(Bytes.toBytes("colfam1"));
try{
boolean res4 = table.checkAndDelete(Bytes.toBytes("row1"),
Bytes.toBytes("colfam1"), Bytes.toBytes("qual1"),
Bytes.toBytes("val1"), delete3);
System.out.println("Delete 3 successful: " + res4);
} catch (Exception e) {
System.err.println("Error: " + e.getMessage()); //아래와 같이 에러가 발생한다. 앞에 조건은 부합하지만 delete3에서는 존재하지 않는 row2에 대해 언급했기때문이다.
}hbase(main):028:0> scan 'testtable'
ROW COLUMN+CELL
row1 column=colfam1:qual1, timestamp=1, value=val1
row1 column=colfam1:qual2, timestamp=2, value=val2
row1 column=colfam2:qual1, timestamp=1, value=val1
row1 column=colfam2:qual2, timestamp=2, value=val2
1 row(s)
Took 0.0417 secondsDelete 1 successful: false
Delete 2 successful: true
Error: Failed 1 action: org.apache.hadoop.hbase.DoNotRetryIOException: Action's getRow must match
at org.apache.hadoop.hbase.regionserver.HRegion.checkMutationType(HRegion.java:4149)
at org.apache.hadoop.hbase.regionserver.HRegion.checkAndMutate(HRegion.java:4029)
at org.apache.hadoop.hbase.regionserver.RSRpcServices.mutate(RSRpcServices.java:2837)
at org.apache.hadoop.hbase.shaded.protobuf.generated.ClientProtos$ClientService$2.callBlockingMethod(ClientProtos.java:42000)
at org.apache.hadoop.hbase.ipc.RpcServer.call(RpcServer.java:409)
at org.apache.hadoop.hbase.ipc.CallRunner.run(CallRunner.java:130)
at org.apache.hadoop.hbase.ipc.RpcExecutor$Handler.run(RpcExecutor.java:324)
at org.apache.hadoop.hbase.ipc.RpcExecutor$Handler.run(RpcExecutor.java:304)
: 1 time, servers with issues: netdb.slave1.com,16020,1534483984776이번에는 checkandMutate를 실험해보자. 아래 코드를 보면 RowMutations라는 객체를 생성해서 확인을 하고 있다.
import org.apache.hadoop.hbase.filter.CompareFilter;
Table table = connection.getTable(TableName.valueOf("testtable"));
Put put = new Put(Bytes.toBytes("row1"));
put.addColumn(Bytes.toBytes("colfam1"),Bytes.toBytes("qual1"),1,Bytes.toBytes("val1"));
put.addColumn(Bytes.toBytes("colfam1"),Bytes.toBytes("qual2"),2,Bytes.toBytes("val2"));
put.addColumn(Bytes.toBytes("colfam1"),Bytes.toBytes("qual3"),3,Bytes.toBytes("val3"));
put.addColumn(Bytes.toBytes("colfam2"),Bytes.toBytes("qual1"),1,Bytes.toBytes("val1"));
put.addColumn(Bytes.toBytes("colfam2"),Bytes.toBytes("qual2"),2,Bytes.toBytes("val2"));
put.addColumn(Bytes.toBytes("colfam2"),Bytes.toBytes("qual3"),3,Bytes.toBytes("val3"));
table.put(put);
Put put2 = new Put(Bytes.toBytes("row1"));
put2.addColumn(Bytes.toBytes("colfam1"), Bytes.toBytes("qual1"),
4, Bytes.toBytes("val99"));
put2.addColumn(Bytes.toBytes("colfam1"), Bytes.toBytes("qual4"),
4, Bytes.toBytes("val100"));
Delete delete = new Delete(Bytes.toBytes("row1"));
delete.addColumn(Bytes.toBytes("colfam1"), Bytes.toBytes("qual2"));
RowMutations mutations = new RowMutations(Bytes.toBytes("row1"));
mutations.add(put2);
mutations.add(delete);
boolean res1 = table.checkAndMutate(Bytes.toBytes("row1"),
Bytes.toBytes("colfam2"), Bytes.toBytes("qual1"),
CompareFilter.CompareOp.LESS, Bytes.toBytes("val1"), mutations);
System.out.println("Mutate 1 successful: " + res1); row1 colfam2:qual1 value의 값(1)과 val1과 비교한다. 더 작지 않기때문에 false
Put put3 = new Put(Bytes.toBytes("row1"));
put3.addColumn(Bytes.toBytes("colfam2"), Bytes.toBytes("qual1"), //row1 colfam2:qual1 value 값을 2로 변경한다.
4, Bytes.toBytes("val2"));
table.put(put3);
boolean res2 = table.checkAndMutate(Bytes.toBytes("row1"),
Bytes.toBytes("colfam2"), Bytes.toBytes("qual1"), 비교하면 row1 colfam2:qual1의 값(2)보다 val1이 더작다 true
CompareFilter.CompareOp.LESS, Bytes.toBytes("val1"), mutations); //true이기때문에 mutations의 OP가 수행된다.
System.out.println("Mutate 2 successful: " + res2);Mutate 1 successful: false
Mutate 2 successful: truehbase(main):007:0> scan 'testtable'
ROW COLUMN+CELL
row1 column=colfam1:qual1, timestamp=4, value=val99
row1 column=colfam1:qual3, timestamp=3, value=val3
row1 column=colfam1:qual4, timestamp=4, value=val100
row1 column=colfam2:qual1, timestamp=4, value=val2
row1 column=colfam2:qual2, timestamp=2, value=val2
row1 column=colfam2:qual3, timestamp=3, value=val3
1 row(s)
Took 0.0747 seconds'2018년 > DataBase' 카테고리의 다른 글
3장 클라이언트 API : 기본기능 - 스캔 (0) 2018.08.18 3장 클라이언트 API : 기본기능 - 일괄처리 연산 (0) 2018.08.17 3장 클라이언트 API : 기본기능 - Get 메서드 (0) 2018.08.17 3장 클라이언트 API : 기본기능 - Put 메서드 (0) 2018.08.10 험난한 HBASE 설치기 (0) 2018.07.17