Log In
|
Sign Up
Search
한글 검색 필드를 음소 분해&수치화 하여 정렬절에 사용할 경우 검색 속도 차이 (K언어/JAVA)
Writer
정종인
Description
한글 검색 필드를 음소 분해&수치화 하여 정렬절에 사용할 경우 검색 속도 차이에 대한 테스트 결과입니다 > 테스트 조건 1) 음절은 한글 문자만 유효하며 특수문자, 영어, 숫자, 한자 등의 문자는 제외하고 숫자로 치환합니다. ---------- 2) 음절당 각 한 개의 초성, 중성, 종성의 음소로 분해되며, 종성이 없는(받침이 없는) 문자의 경우에도 원활한 정렬을 위해 두 자릿수 숫자를 부여하였습니다. 예) 기존 가 -> [“ㄱ”, “ㅏ”, “”] > [“01”, “01”, “0”] 초성과 중성이 있으나 종성(받침)이 없습니다. 각 -> [“ㄱ”, “ㅏ”, “ㄱ”] > 초성과 중성, 종성이 [“01”, “01”, 01”]로 치환됩니다. 변경 후 가 -> [“ㄱ”, “ㅏ”, “”] > [“01”, “01”, “00”] 종성 없는 경우 “0”이 아닌 “00”으로 치환됩니다 따라서 한 음절당 6자릿수의 숫자로 치환됩니다 ---------- 3) 치환된 숫자는 10의 최소값을 갖도록 설정하였습니다. 각 음소를 치환했을 때 첫 번째 음절의 초성이 01~09의 숫자로 치환되었을 경우 INT속성의 필드에서 가장 앞자릿수 0을 소거시키는 현상이 발생됩니다. 예) 011226 > 11226 (검색엔진에 INT로 색인 시) 이에 따라 초성, 중성은 각 9를 더해 10부터 최소 10의 값을 가지고, 종성은 10을 더하여 빈 값의 경우에도 최소 10의 값을 가질 수 있도록 구성하였습니다. 가 -> [“ㄱ”, “ㅏ”, “”] > [“10”, “10”, “10”] 각 -> [“ㄱ”, “ㅏ”, “ㄱ”] > [“10”, “10”, “11”] 초성과 종성의 동일한 자음 문자가 같은 값을 가질 수 있도록, 또는 문자의 순서를 세는데에 일관성을 가질 수 있도록 초성, 중성, 종성의 최소값을 10으로 설정하였습니다. ---------- 4) 음절 당 6자리수 숫자 치환 형식으로 진행하였습니다. [음절 > 음소 > 숫자] 치환 단계에서 치환 되는 문자열 개수가 3개를 초과할 경우 INT64필드의 최대값을 초과하여 색인 시 에러가 발생합니다. 그러므로 INT64필드의 치환 전 문자열을 3음절로 설정하였습니다. 아스키코드 기준 첫 번째 한글인 “가”부터 마지막 한글인 “힣”까지 총 11,172개의 한글로 구성되어 있으므로 한글 전체 문자를 음소분해 수치화할 경우 한 음절 당 5자릿수 숫자로 구성할 수 있는 것으로 확인됩니다. 일반적으로 사용하지 않는 [묰, 걼, 꼍]와 같은 비 완성형 한글 문자를 제외하고 완성형 한글은 2,350개로 구성되어 음절 당 4자릿수 구성 또한 가능하며 이 경우 사용 가능한 음절 개수는 최대 4~5개로 추정됩니다. 사용 가능 음절 개수와 별개로 치환 된 INT필드의 자리수에는 큰 차이가 없는 것으로 확인되어, (필드 속성에 따른 정렬 속도 테스트이므로) 음절 당 6자리수 숫자 치환 형식으로 진행하였습니다. ---------- 5) 유의미한 결과 데이터 도출을 위하여 다음과 같은 경우는 결과 데이터에서 제외하였습니다. 검색 테스트 확인 결과 평균 3~7ms 의 검색 속도를 보이나, 간혹 15ms를 초과하는 현상이 발생됩니다. - 검색 필드의 속성에 따른 검색 속도 차이가 아닌 타 요소(CPU, 메모리 등)에 영향을 받은 것으로 판단 될 경우 - 정렬 필드 변경(쿼리 변경) 후 첫 검색 시 캐시되어 평균 검색 속도가 100ms 이상인 경우 [검색엔진_튜닝.pdf][1] 위 내용에서 3번 목차를 참고하였습니다. ---------- 6) 초성, 중성, 종성의 배열 순서는 다음과 같습니다. 초성: [ㄱ, ㄲ, ㄴ, ㄷ, ㄸ, ㄹ, ㅁ, ㅂ, ㅃ, ㅅ, ㅆ, ㅇ, ㅈ, ㅉ, ㅊ, ㅋ, ㅌ, ㅍ, ㅎ] 중성: [ㅏ, ㅐ, ㅑ, ㅒ, ㅓ, ㅔ, ㅕ, ㅖ, ㅗ, ㅘ, ㅙ, ㅚ, ㅛ, ㅜ, ㅝ, ㅞ, ㅟ, ㅠ, ㅡ, ㅢ, ㅣ] 종성: ['', ㄱ, ㄲ, ㄳ, ㄴ, ㄵ, ㄶ, ㄷ, ㄹ, ㄺ, ㄻ, ㄼ, ㄽ, ㄾ, ㄿ, ㅀ, ㅁ, ㅂ, ㅄ, ㅅ, ㅆ, ㅇ, ㅈ, ㅊ, ㅋ, ㅌ, ㅍ, ㅎ] ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- > 테스트 필드 종류 및 특징 1번 필드 - title 필드 속성 STRING VERBATIM 특징: 한글로 구성된 문자열 예시) 강원도 강릉시 강동면 언덕밑길 심백권 ---------- 2번 필드 - title_int 필드 속성 INT64 특징: 한글 필드 1~3번째 음절 음소 분해 > 숫자로 치환 예시) 101031212414131810 ---------- 3번 필드 - title_int_str 필드 속성 STRING VERBATIM 특징: 한글 필드 1~3번째 음절 음소 분해 > 숫자로 치환 예시) 101031212414131810 ---------- 4번 필드 - title_str_full 필드 속성 STRING VERBATIM 특징: 한글 필드의 모든 문자열을 음소 분해, 각 음소를 10 이상의 두 자릿수 숫자로 치환 (글자 수 제한없이 전체 문자열을 변환) 예시) 101031212414131810101031152831193010101031131831161614211414131411163035103018193026171111102414 ---------- > 예시데이터 ---------- title (52): 강원도 강릉시 강동면 언덕밑길 심백권 title_int (18): 101031212414131810 title_int_str (18): 101031212414131810 title_str_full (96): 101031212414131810101031152831193010101031131831161614211414131411163035103018193026171111102414 ---------- > 테스트 방법 1) 필드 별로 정렬하여 1,000회 이상 검색 시도 2) 유의미하지 않은 것으로 판단되는 데이터 제외 후 1,000건 추출 3) 추출 된 1,000건의 데이터로 검색 속도 평균값 추출 (전체 검색 건 수 소요 시간 총합 / 검색 건 수) ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- > 첫 번째 테스트 테이블 정보 (전체 데이터 건 수: 10,000건) [필드명, 필드 타입, 최대, 최소, 평균] [title, String Verbatim Null, 104, 45, 54.94] [title_int, Int64 Null, 18, 18, 18.00] [title_int_str, String Verbatim Null, 18, 18, 18.00] [title_str_full, String Verbatim Null, 192, 84, 99.08] 1) order by title asc - 평균 2.965ms 2) order by title_int asc - 평균. 2.923ms 3) order by title_int_str asc - 평균 2.904ms 4) order by title_str_full asc - 평균 3.017ms 테스트 결과, 검색 속도에 큰 차이가 없는 것으로 확인 됩니다 테이블의 데이터 건 수가 적은 관계로 위와 같은 결과가 도출되었다고 판단하여, 대량의 데이터 적재 후 두 번째 테스트 진행 ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- > 두 번째 테스트 테이블 정보 (전체 데이터 건 수: 6,452,744건) [필드명, 필드 타입, 최대, 최소, 평균] [title, String Verbatim Null, 132, 36, 54.67] [title_int, Int64 Null, 18, 18, 18.00] [title_int_str, String Verbatim Null, 18, 18, 18.00] [title_str_full, String Verbatim Null, 252, 66, 99.88] 1) order by title asc - 평균 3.250ms 2) order by title_int asc - 평균. 3.048ms 3) order by title_int_str asc - 평균 3.025ms 4) order by title_str_full asc - 평균 3.267ms ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- > 결론 데이터 건 수 차이를 두고 두 차례의 테스트를 진행해보았으나, 검색 속도 순위는 동일한 것으로 확인되었습니다. 필드별 정렬절 사용 시 빠른 검색 속도 순위는 다음과 같습니다. 1) 3음절만 숫자로 치환한 STRING필드 2) 3음절만 숫자로 치환한 INT필드 3) 한글 STRING필드 4) 한글 전체를 숫자로 치환한 STRING필드 ---------- >JAVA 대신 K언어로 사용할 경우 사전 설정은 다음과 같습니다. 1) Connector rc파일 설정 중 charset 속성 EUC-KR: charset = EUC-KR UTF-8: charset = UTF-8 (charset 다를 경우 한글로 인식하지 않습니다) 2) dml.kql 파일의 인코딩 설정 EUC-KR notepad로 파일 열기, 상단 탭 중 인코딩 탭에서 charset 설정 EUC-KR: 문자 집합 > 한국어 > EUC-KR UTF-8: 문자 집합 > UTF-8 (charset 다를 경우 초성, 중성, 종성에 대해 선언한 사전 key값과 음소분해한 문자의 일치 여부를 확인하여 숫자값을 부여하는 부분에서 정상적인 문자 대조가 불가합니다.) 3) dml.kql파일 중 pasing_str메소드에서 splitg메소드의 charset 설정 EUC-KR: splitg('euckr') UTF-8: splitg('utf8') 4) 명령 프롬프트 창에서 명령어 입력으로 charset 설정 EUC-KR: chcp 949 입력 UTF-8: chcp 65001 입력 (charset 일치시켜야 한글 깨짐 없이 정상적인 결과 확인이 가능합니다.) 위의 내용에 대해 EUC-KR 또는 UTF-8로 모든 설정을 일치시켜주어야 정상적으로 스크립트가 실행되며, 결과를 확인하실 수 있습니다. 다음은 java 언어를 대신해 K언어를 사용 할 경우의 코드입니다. k언어사용dml.kql (첨부파일 참고) dict chodict = {'ㄱ':'10', 'ㄲ':'11', 'ㄴ':'12', 'ㄷ':'13', 'ㄸ':'14', 'ㄹ':'15', 'ㅁ':'16', 'ㅂ':'17', 'ㅃ':'18', 'ㅅ':'19', 'ㅆ':'20', 'ㅇ':'21', 'ㅈ':'22', 'ㅉ':'23', 'ㅊ':'24', 'ㅋ':'25', 'ㅌ':'26', 'ㅍ':'27', 'ㅎ':'28'}; dict jungdict = {'ㅏ':'10', 'ㅐ':'11', 'ㅑ':'12', 'ㅒ':'13', 'ㅓ':'14', 'ㅔ':'15', 'ㅕ':'16', 'ㅖ':'17', 'ㅗ':'18', 'ㅘ':'19', 'ㅙ':'20', 'ㅚ':'21', 'ㅛ':'22', 'ㅜ':'23', 'ㅝ':'24', 'ㅞ':'25', 'ㅟ':'26', 'ㅠ':'27', 'ㅡ':'28', 'ㅢ':'29', 'ㅣ':'30'}; dict jongdict = {'':'10', 'ㄱ':'11', 'ㄲ':'12', 'ㄳ':'13', 'ㄴ':'14', 'ㄵ':'15', 'ㄶ':'16', 'ㄷ':'17', 'ㄹ':'18', 'ㄺ':'19', 'ㄻ':'20', 'ㄼ':'21', 'ㄽ':'22', 'ㄾ':'23', 'ㄿ':'24', 'ㅀ':'25', 'ㅁ':'26', 'ㅂ':'27', 'ㅄ':'28', 'ㅅ':'29', 'ㅆ':'30', 'ㅇ':'31', 'ㅈ':'32', 'ㅊ':'33', 'ㅋ':'34', 'ㅌ':'35', 'ㅍ':'36', 'ㅎ':'37'}; string pasing_str(string s){ var a = s.splitg('euckr'); string strResult=""; tuple
x; for x in a if(x[0] in chodict.keys()) strResult+=chodict[x[0]]+jungdict[x[1]]+jongdict[x[2]]; return strResult; } string get_three_replace(string s){ return pasing_str(s)[:17]; } string get_all_replace(string s){ return pasing_str(s); } void main(string idx_cc_sz="") { ECHO "[IMPORT DATA - BEGIN: address3]"; if (idx_cc_sz=="") { USE VOLUME temp; } else { USE VOLUME address3; } if (idx_cc_sz=="") { IMPORT FILES ../rawdata/address3/bulk *.fgf TO address3 THROUGH gw_address3 TRANSFORM title_int = get_three_replace(title), title_int_str=get_three_replace(title), title_str_full=get_all_replace(title) OPERATION UPDATE_OR_INSERT; } else { IMPORT FILES ../rawdata/address3/bulk *.fgf TO address3 THROUGH gw_address3 OPERATION STORE parallel 1 indexing_cache_size = 100 MB; } stmtout("BUILD INDEX TO address3 %s;".format( idx_cc_sz=="" ? "" : "parallel 1 indexing_cache_size="+idx_cc_sz)); ECHO "[IMPORT DATA - END: address3]"; } [1]: http://iris.konantech.com/download/attachments/716406830/%EA%B2%80%EC%83%89%EC%97%94%EC%A7%84_%ED%8A%9C%EB%8B%9D.pdf
Tag
음소 분해 수치화 정렬절 검색 속도 차이 K언어
Module Name
Attachments
Test.java (2.0kb)
k언어사용dml.kql (2.1kb)
Comments
Save
Save
Cancel
Save
Cancel
Warning
Login