fingerprint 검색(bitand) 0 9 3,157

by park1q [Oracle Tuning] fingerprint bitand [2010.12.13 13:08:48]



갑자기 친구한테서 문의가 들어왔는데..잘 안되서 질문 드립니다.
fingerprint 라고 화합물의 구조를 담고 있는 t_bit 테이블에서 해당 구조를 만족하는 id 를 가져오는 쿼리의 성능 문제입니다.
원래는 fp0 ~ fp15까지 64byte 를 담고 있는 테이블인데, 간단한 테스트를 위해 다음과 같이 생성했습니다.

참고자료(여기서는 인덱스를 고려하지 않았으며,Mysql 로 fp1&255=255 라고 bitand 대신 사용했습니다.)
http://depth-first.com/articles/2008/10/02/fast-substructure-search-using-open-source-tools-part-1-fingerprints-and-databases/


create table t_bit (
id number ,
fp1 number,
fp2 number,
fp3 number,
fp4 number,
fp5 number,
fp6 number,
fp7 number,
fp8 number)

insert into t_bit
select
level lvl,
round(dbms_random.value*1000000000000) fp1,
round(dbms_random.value*1000000000000) fp2,
round(dbms_random.value*1000000000000) fp3,
round(dbms_random.value*1000000000000) fp4,
round(dbms_random.value*1000000000000) fp5,
round(dbms_random.value*1000000000000) fp6,
round(dbms_random.value*1000000000000) fp7,
round(dbms_random.value*1000000000000) fp8
from dual connect by level <=100000 ;

BEGIN
  dbms_stats.gather_table_stats(user,'T_BIT') ;
END ;
/

*** row 조회용 쿼리 예
select * from t_bit A
 where bitand(fp1, 255)=255 and bitand(fp2, 255)=255 and bitand(fp3, 16384)=16384
 
*** plan 
SELECT STATEMENT, GOAL = ALL_ROWS   251 1 68
 TABLE ACCESS FULL EV T_BIT 251 1 68


*** 질문
16개의 인덱스를 추가해도 되는데, 어떤 방법이 가장 효율적일까요? 데이타는 현재 2천만건이랍니다.
인덱스를 사용하여 빠른 Access 를 할수 있도록 개인적으로 모든 칼럼에 혹시나 하는 마음에 아래와 같이 인덱스를 추가 했지만 아무런 성능 개선이 없습니다.
방법이 없는걸까요? bitmap index 나 function based index 외 다른게 필요할것 같기도 하네요.
조언 부탁 드립니다.

by 마농 [2010.12.14 16:52:42]
지문 인식 시스템인가요?
정확한 로직을 몰라 뭐라 말씀드리긴 곤란하지만...
비트맵인덱스가 해결방안이 되지 않을까? 조심스레 생각해 봅니다.

아래 스터디때 정리되었던 비트맵인덱스의 특성입니다.
http://wiki.gurubee.net/pages/viewpage.action?pageId=6258817
○ 하나의 비트맵 인덱스 단독으로는 쓰임새가 별로 없지만 여러 비트맵 인덱스를 동시에 사용할 수 있다는 특징 때문에 대용량 데이터 검색 성능을 향상 시키는 데에 큰 효과를 발휘한다.
○ 두 개 이상 비트맵을 이용한 Bitwise AND 연산뿐만 아니라 Bitwise OR, Bitwise Not 연산도 가능하다.
○ 비트맵 인덱스는 여러 인덱스를 동시에 활용할 수 있다는 장점 때문에 다양한 조건절이 사용되는, 특히 정형화되지 않은 임의 질의가 많은 환경에 적합하다.

by park1q [2010.12.14 21:58:06]
바쁘신데..관심가져 주셔서 감사합니다.
음..이 이슈를 좀 찾아봤는데..질문은 있는데..답이 없더군요.
지문인식 시스템은 아니고, 화합물의 특성을 기록하고 있는 1024byte 를 저장하고 있는 64byte(10진수) * 16 개의 칼럼으로 구성된 테이블입니다.
2진수의 bitand(1111,111), 즉 bitand(17,7)=7 라면 조건을 만족하는 것으로 보는거죠. insert 되는 특성은 모르겠는데, 그렇게 연산을 하더군요.
실제 다른 외국 포럼에도 질문한 내용을 보면 수천만건 이상에서 17초 정도 속도가 나오는데, function based index 사용을 하라는데, 답변이 잘못되어 있어서요.
테스트는 위의 예제로 간단하게 할수 있습니다. 단 full scan 을 어떻게든 막아라~~
이게 미션입니다.
설계상의 오류일수도 있겠으나, 실제 이렇게 많이 사용하고 있는것으로 보아 그럴수 밖에 없는것 같기도 하네요.
저도 천천히 틈날때 생각해 보겠습니다.
google에서 bitand function 으로 찾은 문서 url 입니다.
아래있는 답은 잘못되었구요.
http://www.experts-exchange.com/Database/Oracle/Q_20789955.html

by park1q [2010.12.15 08:10:58]
쿼리 예제가 조금 잘못되어서 수정합니다.
전제가 모든 16개 칼럼의 조건은 equal 로 되어 있습니다.
에게 왠지 단서가 될수 있다는 생각을 해 봅니다.

select * from t_bit A
where bitand(fp1, 255)=255 and bitand(fp2, 255)=255 and bitand(fp3, 16384)=16384 ~..~ and bitand(fp8, 255)=255

by 마농 [2010.12.15 11:28:40]
FBI 와 BITMAP 을 함께 사용하면 엄청난 성능향상이 기대됩니다.

CREATE BITMAP INDEX x01_t_bit ON t_bit(DECODE(BITAND(fp1, 255), 255, 1, 0));
CREATE BITMAP INDEX x02_t_bit ON t_bit(DECODE(BITAND(fp2, 255), 255, 1, 0));
CREATE BITMAP INDEX x03_t_bit ON t_bit(DECODE(BITAND(fp3, 16384), 16384, 1, 0));
CREATE BITMAP INDEX x04_t_bit ON t_bit(DECODE(BITAND(fp4, 255), 255, 1, 0));
CREATE BITMAP INDEX x05_t_bit ON t_bit(DECODE(BITAND(fp5, 255), 255, 1, 0));
CREATE BITMAP INDEX x06_t_bit ON t_bit(DECODE(BITAND(fp6, 255), 255, 1, 0));
CREATE BITMAP INDEX x07_t_bit ON t_bit(DECODE(BITAND(fp7, 255), 255, 1, 0));
CREATE BITMAP INDEX x08_t_bit ON t_bit(DECODE(BITAND(fp8, 255), 255, 1, 0));

SELECT *
FROM t_bit
WHERE DECODE(BITAND(fp1, 255), 255, 1, 0) = 1
AND DECODE(BITAND(fp2, 255), 255, 1, 0) = 1
AND DECODE(BITAND(fp3, 16384), 16384, 1, 0) = 1
AND DECODE(BITAND(fp4, 255), 255, 1, 0) = 1
AND DECODE(BITAND(fp5, 255), 255, 1, 0) = 1
AND DECODE(BITAND(fp6, 255), 255, 1, 0) = 1
AND DECODE(BITAND(fp7, 255), 255, 1, 0) = 1
AND DECODE(BITAND(fp8, 255), 255, 1, 0) = 1
;

Plan
SELECT STATEMENT ALL_ROWSCost: 3 Bytes: 117 Cardinality: 1
-6 TABLE ACCESS BY INDEX ROWID TABLE HMS.T_BIT Filter Predicates: DECODE(BITAND("FP3",16384),16384,1,0)=1 AND DECODE(BITAND("FP5",255),255,1,0)=1 AND DECODE(BITAND("FP6",255),255,1,0)=1 AND DECODE(BITAND("FP7",255),255,1,0)=1 AND DECODE(BITAND("FP8",255),255,1,0)=1 Cost: 3 Bytes: 117 Cardinality: 1
--5 BITMAP CONVERSION TO ROWIDS
---4 BITMAP AND
----1 BITMAP INDEX SINGLE VALUE INDEX (BITMAP) HMS.X01_T_BIT Access Predicates: DECODE(BITAND("FP1",255),255,1,0)=1
----2 BITMAP INDEX SINGLE VALUE INDEX (BITMAP) HMS.X02_T_BIT Access Predicates: DECODE(BITAND("FP2",255),255,1,0)=1
----3 BITMAP INDEX SINGLE VALUE INDEX (BITMAP) HMS.X04_T_BIT Access Predicates: DECODE(BITAND("FP4",255),255,1,0)=1

by park1q [2010.12.15 15:34:44]
설명을 제대로 못한건지..죄송..

bitand(fp1,변수1)=변수1 이렇답니다. 그게 16개 연결되어 있구요.
따라서 그냥 FBI 를 절대로 사용할수 없습니다.
예제에는 제가 255 라고 했지만 실제로는 다른 조건이 들어 오죠..

이런 로직을 함 생각해 봤느데..도저히..답이 없어 보입니다.
칼럼이 많고 적고를 떠나서 그냥

fp1&n1=n1 를 fn(fp1)=n1 으로 바꿔야 되는데..이건 n1 이 가변이라 절대로 안될꺼 같습니다.

여기 글쓰면서 불연듯 생각난건데..bitmap join 인덱스가 생각 나네요.
조회되는 변수도 n1 ~ n16 이라면 그걸 where 절에 넣지 말고 condition 이라는 테이블 만들어 놓고 join 을 하면..될것도 같은데.. 함 해보고 갱신하겠습니다.

by park1q [2010.12.15 15:55:24]
안되는 기능인가봅니다.

condition 이라는 1row 테이블을 생성하고 bitmap join index 에 bitand 를 넣고 다음과 같이 인덱스를 생성할수 있음 되겠다 싶었는데..

create bitmap index t_bit3_bx01
on t_bit3 (bitand(a.fp1,b.n1),bitand(a.fp2,b.n2),bitand(a.fp3,b.n3),bitand(a.fp4,b.n4))
from t_bit3 a, t_condition b
where b.id = 1

ORA-25953: 조인 인덱스는 함수 인덱스가 될 수 없음

처음에 간단한 문제일거라고 접근 했는데, 도무지..방법이 없는것 같습니다.

여기서 단 하나남은게..도메인 인덱스인데..이건 당췌 샘플이 없어서..

요것도 시간 나면 한번 도전해보겠습니다.

by 마농 [2010.12.15 16:29:33]
조건으로 입력되는 n1의 값의 종류가 제한적일것 같다는 생각이 듭니다.
몇가지 종류의 값이 입력되나요?

by park1q [2010.12.15 16:42:49]
방금 통화했는데..n1 ~ n16 모두 이론적으로 2^64 - 1 개 만큼의 숫자가 올수 있답니다.

by park1q [2010.12.16 08:08:07]
결국 기존 RDB로는 딱히 좋은 솔루션이 없음을 알았습니다.
이미지,오디오등을 검색할수 있는 spatial db 를 사용하면 어쩌면 해법이 있을수도 있을것 같은데..제 밥그릇이 아니라서..일단 여기서 홀딩합니다.
감사합니다.
댓글등록
SQL문을 포맷에 맞게(깔끔하게) 등록하려면 code() 버튼을 클릭하여 작성 하시면 됩니다.
로그인 사용자만 댓글을 작성 할 수 있습니다. 로그인, 회원가입