인덱스 바이너리

마지막 업데이트: 2022년 5월 28일 | 0개 댓글
  • 네이버 블로그 공유하기
  • 네이버 밴드에 공유하기
  • 페이스북 공유하기
  • 트위터 공유하기
  • 카카오스토리 공유하기
만약 책이 한 권 있고 우리가 451페이지를 찾는 방법은?여러 가지가 있겠지만 그중 우리가 무의식적으로 쓰는 방법을 생각해보면 책의 중간쯤을 펴고 만약 451보다 인덱스 바이너리 작은 페이지라면 거기서부터 뒷부분을, 451보다 큰 페이지라면 앞부분을 찾아볼 것이다.이런 방법을 반복하는 탐색 방법이 이진 탐색이다.

인덱스 바이너리

바이너리 업그레이드 또는 바이너리 다운 그레이드는 테이블을 덤프하고 다시로드하지 않고 버전의 MySQL을 기존 버전에 "in-place"에서 설치합니다.

기존 버전의 서버가 동작하고있는 경우는 그것을 중지합니다.

다른 버전의 MySQL을 설치합니다. 새 버전이 원래 버전보다 최신 경우 업그레이드가 오래된 경우 다운 그레이드됩니다.

새로운 버전의 서버를 시작합니다.

종종 MySQL의 이전 버전의 테이블은 새 버전에서 문제없이 사용할 수 있습니다. 그러나이 섹션에서 인덱스 바이너리 설명한대로 테이블 또는 테이블의 인덱스를 다시 작성해야 할 것 같은 변경이 발생할 수도 있습니다. 여기에서 설명하는 문제 중 하나의 영향을받는 테이블이있는 경우는 필요에 따라 테이블 또는 인덱스를 섹션 2.11.4 "테이블 또는 인덱스를 다시 만들거나 복구" 에서 설명한 절차를 사용하여 다시 구축합니다.

테이블의 비 호환성

ARCHIVE 테이블을 포함하는 MySQL 5.0 설치에서 MySQL 5.1로 바이너리 업그레이드 후이 테이블에 액세스하면 mysql_upgrade 또는 CHECK TABLE . FOR UPGRADE 를 실행되어있는 경우에도 서버가 충돌합니다. 이 문제를 해결하려면 업그레이드 전에 mysqldump를 사용하여 모든 ARCHIVE 테이블을 덤프하고 업그레이드 후에는 MySQL 5.1에 다시로드합니다. MySQL 5.1에서 5.0으로 바이너리 다운 그레이드에서도 같은 문제가 발생합니다.

업그레이드 문제는 MySQL 5.6.4에서 수정되어 있습니다. 서버는 MySQL 5.0에서 작성된 ARCHIVE 테이블을 엽니 다. 그러나 계속 권장되는 업그레이드 절차는 업그레이드 전에 5.0 ARCHIVE 테이블을 덤프하고 업그레이드 후 다시로드하는 방법입니다.

인덱스의 비 호환성

MySQL 5.6.3에서는 ROW_FORMAT=DYNAMIC 또는 ROW_FORMAT=COMPRESSED 을 사용하는 InnoDB 테이블은 인덱스 프리픽스 키의 길이 제한은 767 바이트에서 3072 바이트로 증가했습니다. 자세한 내용은 섹션 14.6.7 "InnoDB 테이블에서의 제한" 을 참조하십시오. 이 변경은 MySQL 5.5.14에 포팅되어 있습니다. 이러한 이상 릴리스 중 하나에서 길이 제한이 짧은 이전 버전으로 다운 그레이드 할 경우 인덱스 프리픽스 키를 767 바이트로 잘릴 수 있습니다. 그렇지 않으면 다운 그레이드가 실패 할 수 있습니다. 이 문제는 다운 그레이드 서버에서 구성 옵션 innodb_large_prefix 이 유효했던 경우에만 발생할 수 있습니다.

테이블의 덤프 및 리로드를 실행하지 않고 바이너리 업그레이드를 수행하는 경우, MySQL 4.1에서 5.1로 직접 업그레이드 할 수 없습니다. 이것은 MySQL 5.0의 MyISAM 테이블 인덱스의 형식과 호환되지 않는 변경에 의한 것입니다. MySQL 4.1에서 5.0으로 업그레이드하고 모든 MyISAM 테이블을 복구하십시오. 그 후, MySQL 5.0에서 5.1로 업그레이드. 테이블을 확인하고 복구합니다.

문자 세트 또는 데이터 정렬 처리의 변경으로 인해 문자 집합의 순서가 변경 될 수 있으며, 따라서 영향을받는 문자 세트 또는 데이터 정렬을 사용하는 인덱스 항목의 순서가 잘못 될 수 있습니다. 이러한 변경에서 몇 가지 문제가 발생할 수 있습니다.

비교 결과가 이전의 결과와 다른

인덱스 항목의 순서 지정이 잘못되어 일부 인덱스 값을 찾을 수 없습니다

ORDER BY 결과의 순서화가 잘못

CHECK TABLE 에 의해보고되는 테이블을 복구 할 필요가있다

이러한 문제의 해결 방법은 인덱스를 삭제하고 다시 만들거나 전체 인덱스 바이너리 테이블을 덤프하고 다시로드하면 영향을받는 문자 세트 또는 데이터 정렬을 사용하는 인덱스를 다시 작성하는 것입니다. 경우에 따라서는 영향을받는 컬럼을 변경하여 다른 데이터 정렬을 사용하도록 할 수 있습니다. 인덱스 재 작성 내용은 섹션 2.11.4 "테이블 또는 인덱스를 다시 만들거나 복구" 를 참조하십시오.

다시 구축해야하는 인덱스가 테이블에 있는지 여부를 확인하려면 다음 목록을 참조하십시오. 이 목록은 인덱스의 재 구축이 필요한 문자 집합 또는 데이터 정렬 변경이 도입 된 MySQL 버전을 보여줍니다. 각 항목은 변경 한 버전과 그 변경의 영향을받는 문자 세트 또는 데이터 정렬을 보여줍니다. 변경이 특정 버그 리포트에 연결된 경우 버그 번호가 표시되어 있습니다.

이 목록은 바이너리 업그레이드 및 바이너리 다운 그레이드에 모두 적용됩니다. 예를 들어, Bug # 27877는 MySQL 5.1.24에서 수정 되었기 때문에 5.1.24 이전 버전에서 5.1.24 이상 버전으로 업그레이드 및 5.1.24 이상에서 5.1.24 이전 버전으로 다운 그레이드 에 적용됩니다.

많은 경우 CHECK TABLE . FOR UPGRADE 를 사용하여 인덱스를 다시 작성해야하는 테이블을 식별 할 수 있습니다. 다음 메시지가보고됩니다.

이러한 경우에는 mysqlcheck --check-upgrade 또는 mysql_upgrade도 사용할 수 있습니다. 이들은 CHECK TABLE 을 실행합니다. 그러나 CHECK TABLE 을 사용할 수는 다운 그레이드가 아닌 업그레이드 뒤뿐입니다. 또한 CHECK TABLE 은 모든 스토리지 엔진에 적용 할 수있는 것은 없습니다. CHECK TABLE 가 지원하는 스토리지 엔진 자세한 내용은 섹션 13.7.2.2 "CHECK TABLE 구문" 을 참조하십시오.

이러한 변경으로 인해 인덱스의 재 구축이 필요합니다.

MySQL 5.1.24 (Bug # 27877)

'ß' LATIN SMALL LETTER SHARP S (독일어)를 포함한 열 utf8_general_ci 또는 ucs2_general_ci 데이터 정렬을 사용하는 인덱스에 영향을줍니다. 이 버그 수정은 원래 데이터 정렬 오류가 수정되었습니다했지만 'ß' 가 이전 다르다는 비교 결과였다 문자 같다는 비교 결과가된다는 비 호환성이 도입되었습니다.

영향을받는 테이블은 MySQL 5.1.30에서 CHECK TABLE . FOR UPGRADE 검출 할 수 있습니다 (Bug # 40053를 참조하십시오).

이 문제의 해결 방법은 MySQL 5.1.62,5.5.인덱스 바이너리 인덱스 바이너리 21 및 5.6.5에서 구현되어 있습니다. 해결 방법은 영향을받는 열을 utf8_general_mysql500_ci 및 ucs2_general_mysql500_ci 데이터 정렬을 사용하도록 변경할 수 있습니다. 이 데이터 정렬은 원래 5.1.24 이전 utf8_general_ci 및 ucs2_general_ci 순서를 유지합니다.

MySQL 5.0.48,5.1.23 (Bug # 27562)

'`' GRAVE ACCENT, '[' LEFT 인덱스 바이너리 SQUARE BRACKET, '\' REVERSE SOLIDUS, ']' RIGHT SQUARE BRACKET, '~' TILDE 중 하나의 문자를 포함하는 컬럼에서 ascii_general_ci 데이터 정렬을 사용하는 인덱스에 영향이 있습니다

영향을받는 테이블은 MySQL 5.1.29에서 CHECK TABLE . FOR UPGRADE 검출 할 수 있습니다 (Bug # 39585를 참조하십시오).

MySQL 5.0.48,5.1.21 (Bug # 29461)

eucjpms , euc_kr , gb2312 , latin7 , macce , ujis 중 하나의 문자 집합을 사용하는 컬럼의 인덱스에 영향이 있습니다

영향을받는 테이블은 MySQL 5.1.29에서 CHECK TABLE . FOR UPGRADE 검출 할 수 있습니다 (Bug # 39585를 참조하십시오).

ZOOMTRADER 바이너리 옵션을 (zoomtrader baineoli obsyeon-eul) Meaning in English - English Translation

Examples of using Zoomtrader 바이너리 옵션을 in a sentence and their translations

Korean - English

English - Korean

Conjugation Contact About Privacy Policy Tr-ex.me 에서 한국어 Thanks

and required to achieve the purposes illustrated in the cookie policy. If you want to know more or withdraw your consent to all or some of the cookies, please refer to the cookie policy .
By closing this banner, scrolling this page, clicking a link or continuing to browse otherwise, you agree to the use of cookies.

Opt-Out of the sale of personal information
We won't sell your personal information to inform the ads you see. You may still see interest-based ads if your information is sold by other companies or was sold previously. Opt-Out Dismiss

[알고리즘] 이진 검색 - Binary Search (Python, Java)

정렬된 인덱스 바이너리 데이터를 검색할 때 가장 널리 사용되는 이진 검색(binary search)에 대해서 알아보겠습니다.

달레 코딩에서 코딩 테스트/인터뷰 준비에 좀 더 특화된 컨텐츠를 만나보세요! 📝

책으로된 영어 사전(요즘은 거의 안 쓰죠? 😓)에서 단어를 찾거나 지역 업소록에서 상호명을 어떻게 찾으시나요? 수백, 수천 페이지가 되는 이러한 책을 맨 첫 페이지부터 한 장씩 넘기면서 찾으시는 분들은 아마 없으실 것입니다. 보통은 대강 중간 쯤 어딘가를 어림잡아서 페이지를 펼쳐본 후에 찾으려는 단어나 업소명과 비교하면서 검색 범위를 좁혀나갈 것입니다. 예를 들어, dog 라는 단어를 찾는데, 처음으로 펼쳐본 페이지에서 bear 이 보인다면 그 페이지 이후의 어딘가를 펼쳐볼 것입니다. 두 번째로 펼쳐본 페이지에서 pig 가 나온다면, 첫번째 페이지와 두번째 페이지 사이의 어딘가를 펼쳐볼 것입니다. 이런식으로 반복을 하다보면 monkey -> cat -> horse -> dragon 식으로 점점 검색 범위가 좁혀지다가 dog 을 만나게 될 것입니다. 영어 사전에서 이러한 방식으로 단어를 찾을 수 있는 이유는 바로 우리는 영어 사전 안의 단어가 알파벳 순으로 정렬되어 있다는 것을 인덱스 바이너리 알고 있기 때문입니다.

이진 검색도 이와 매우 유사한 방식으로 검색 범위를 계속적으로 절반씩 줄여나가면서 원하는 값을 찾아가는 알고리즘입니다. 영어 사전과 같이 데이터가 정렬이 되어 있다면 선형 탐색(linear search)보다 성능이 월등히 좋습니다.

예를 들어, 다음과 같이 알파벳으로 이뤄진 배열에서 G 를 찾아내는 과정은 다음과 같습니다.

먼저, 중간에 있는 인덱스 바이너리 H 와 찾으려는 G 와 비교합니다. G 가 더 작으므로 H 를 포함한 그 이 후 값들은 버릴 수 있습니다.

남은 범위 내에서 다시 중간에 있는 D 를 찾으려는 G 와 비교합니다. 이 번에는 G 가 더 크므로 D 를 포함한 그 이 전 값들은 모두 버릴 수 있습니다.

다시 남은 범위 내에서 중간에 있는 F 와 찾으려는 G 와 비교합니다. 이 번에도 G 가 더 크므로 F 를 포함한 그 이 전 값들은 모두 버릴 수 있습니다.

드디어, 정렬된 배열에서 알파벳 G 를 찾게 되어 있습니다! 🎉

지금까지 설명드린 이진 검색을 먼저 재귀 알고리즘으로 구현해볼까요? 여러 개의 값이 담고 있는 배열 arr 와 찾으려는 값 target 이 주어졌을 때, 찾으려는 값의 인덱스(index)를 반환하는 재귀 함수를 작성해보겠습니다.

low 는 검색 범위의 시작 인덱스를 가르키고, high 는 검색 범위의 종료 인덱스를 가르킵니다. 재귀 알고리즘의 기저 조건(base condition)은 low 가 high 보다 커질 때이며, 이 때는 찾으려는 값이 배열 내에 존재하지 않는 다는 뜻이므로 -1 을 반환합니다. mid 에는 검색 범위의 중앙 인덱스를 저장하고, 이 mid 로 중앙에 있는 값( arr[mid] )을 구하여, 찾으려는 값과 비교합니다.

  • 만약 중앙에 있는 값보다 찾으려는 값이 작다면? 왼편 절반으로 검색 범위를 줄여서 다시 재귀 함수 호출을 합니다.
  • 만약 중앙에 있는 값이 찾으려는 값과 같다면? 찾으려는 값을 찾았으므로 중앙 인덱스( mid )를 반환합니다.
  • 만약 중앙에 있는 값보다 찾으려는 값이 크다면? 오른편 절반으로 검색 범위를 줄여서 다시 재귀 함수 호출을 합니다.

재귀 알고리즘으로 구현한 이진 검색을 테스트 해보겠습니다.

위 함수의 실행 과정을 재귀 호출 트리로 그려보면 다음과 같습니다.

이 재귀 알고리즘은 함수를 호출할 때 마다 검색 범위가 절반으로 줄어들므로 시간 복잡도는 O(log n) 입니다. 재귀 함수의 호출 횟수와 비례햐여 콜 스택의 크기도 커지기 대문에 공간 복잡도도 동일한 O(log n) 입니다.

동일한 알고리즘을 Java로 작성해보았으니 참고바랍니다.

이진 검색은 반복 알고리즘을 사용해서도 어렵지 않게 구현할 수 있습니다. 함수를 재귀적으로 호출하는 대신에 중앙에 있는 값과 비교한 결과에 따라 low 또는 high 값을 적절하게 조정해주기만 하면 됩니다.

맨 처음에는 low 에는 배열의 첫 인덱스( 0 ), high 에는 배열의 마지막 인덱스( len(arr) - 1 )을 설정합니다. 그리고 while 반복문을 이용하여 low 가 high 보다 작거나 같은 동안에 low 또는 high 값을 계속해서 변경해줍니다.

  • 만약 중앙에 있는 값보다 찾으려는 값이 작다면? high 값을 mid - 1 로 변경하여 왼쪽 반쪽을 버립니다.
  • 만약 중앙에 있는 값이 찾으려는 값과 같다면? mid 값을 반환합니다.
  • 만약 중앙에 있는 값보다 찾으려는 값이 크다면? low 값을 mid + 1 로 변경하여 왼쪽 반쪽을 버립니다.

재귀 알고리즘으로 구현한 이진 검색을 테스트 해보겠습니다.

이 반복 알고리즘은 반복문이 매 단계에서 검색 범위가 절반으로 줄어들므로 시간 복잡도는 O(log n) 입니다. 배열이 커진다고 더 많은 공간을 사용하지 않습니다. 동일한 변수( low , high , mid )를 계속해서 재활용하고 있기 때문입니다. 따라서 공간 복잡도는 O(1) 입니다.

동일한 알고리즘을 Java로 작성해보았으니 참고바랍니다.

지금까지 작성한 코드를 보면 중간 인덱스를 구하기 위해서 시작 인덱스와 종료 인덱스를 더한 후 2로 나눕니다.

이 방법은 Java와 같이 인덱스 바이너리 정수 타입이 저장할 수 있는 범위가 정해진 언어의 경우, 엄청 큰 배열이 주어졌을 때, 오버플로우(overflow) 버그를 일으킬 수 있습니다. 이를 방지하기 위해서는 다음과 같이 중간 인덱스를 구하면 됩니다.

이진 검색은 정말 기초적인 알고리즘임에도 불구하고, 막상 직접 구현해보라고 하면 애를 먹는 분들이 많이 있습니다. 실제 개발 업무를 하면서 직접 이진 검색을 구현할 일이 거의 없기 때문일텐데요. 코딩 인터뷰를 앞 두고 계신 분이라면 반드시 숙지해야할 알고리즘이라서 뻔한 내용이지만 한 번 다루어 보았습니다.

인덱스 바이너리

이진검색(Binary Search)에 대해 알아보자. 이진검색 또한 검색 기법중 하나이다. 단 전제조건이 하나가 존재한다.

이진검색을 사용하기 위해서는 해당 배열의 데이터가 정렬(sort)되어있어야 한다.

* 결론적으로 이진검색인 오름차순이나 내림차순으로 정렬된 배열에서 좀 더 효율적으로 검색할 수 있도록 도와주는 알고리즘이라는 것이다.

예시를 하나 들어 [5,7,15,28,29,31,39,58,68,70,95] 라는 리스트가 있고, 나는 여기서 39라는 값을 검색하고 싶다고 가정하자. 가정하자. 우선 검색 범위의 시작 인덱스를 pl, 끝 인덱스를 pr, 중간 인덱스를 pc라고 부르기로 약속하자.

과정에 대한 사진은 다음과 같다.

1) 우선 초기 검색범위는 당연히 처음(index 0)부터 끝(index 10)이다. 그리고 검색범위의 중간 인덱스는 5(0 + 10 // 2)이다. 인덱스 5에 대한 값인 31은 검색하고자 하는 값은 39보다 더 작은 값이다. pl : 0, pr : 10, pc : 5

2) 검색하려는 값이 중간 인덱스의 값보다 더 크기 때문에, 시작 인덱스 값을 중간 인덱스보다 하나 큰 인덱스 6을 시작인덱스로 다시 정한다. 그렇게 되면 6 ~ 10 인덱스가 검색범위이며, 중간 인덱스는 8(6 + 10 // 2) 가 된다. 인덱스 8에 대한 값인 68은 검색하고자 하는 값인 39보다 더 큰 값이다. pl : 6 pr : 10 pc : 8

3) 검색하려는 값이 중간 인덱스의 값보다 작기 때문에 끝 인덱스 값을 중간 인덱스보다 하나 작은 7로 다시 정한다. 그렇게 되면 6~7인덱스가 검색범위이며, 중간인덱스는 6(6 + 7 // 2)이 된다. 인덱스 6의 값은 우리가 찾으려는 값은 39가 있는 인덱스이다. 그렇기 때문에 해당 인덱스인 6을 반환해준다.

* 결론적으로 두가지의 경우를 활용하는 것이다.

x[pl] ~ x[pc]는 key보다 작은것이 되므로 검색 범위에서 제외하는 것이다. 그렇기에 검색범위를 a[pc + 1] ~ a[pr]로 좁혀준다. pl 이 pc + 1이 되는것이다.

x[pc] ~ x[pr]은 key보다 큰 것이 되므로 검색 범위에서 제외하는 것이다. 그렇기에 검색 범위를 a[pl] ~ a[pc - 1]로 좁혀준다. pr 이 pc - 1이 되는 것이다.

검색을 성공하는 경우 : logn - 1

검색을 실패하는 경우 : |log(n+1)| ( 여기서 |x| 는 가우스 기호가 아닌 천장함수이다. 천장함수란 x보다 크거나 같은 수중 가장 작은수를 의미한다. )

young's devlog

테이블에는 인덱스를 작성할 수 있다. 인덱스를 지정하면 얻을 수 있는 효과에 대해 알아보자.

1. 인덱스

인덱스는 테이블에 붙여진 색인으로 검색 속도를 향상시켜주는 역할을 한다.

테이블에 인덱스가 지정되어 있으면 효율적으로 검색할 수 있음으로 WHERE 로 조건이 지정된 SELECT 명령의 처리 속도가 향상된다.

책의 목차나 색인에 제목, 키워드별 페이지 번호가 적혀있듯, 데이터베이스의 인덱스에는 검색 시에 쓰이는 키워드와 대응하는 데이터 행의 장소가 저장되어 있다.

인덱스는 테이블과 별개로 독립된 데이터베이스 객체이다. 그러나 인덱스만으로는 의미가 없기 때문에 테이블에 의존하는 객체라고 볼 수 있다.

대부분의 데이터베이스에서는 테이블을 삭제하면 인덱스도 삭제된다.

2. 검색에 사용하는 알고리즘

데이터베이스의 인덱스에 쓰이는 대표적인 검색 알고리즘으로는 이진 트리해시가 있다.

이진 트리는 탐색 방법이라기보다 데이터 구조에 가깝다.

여기에서의 탐색 방법은 이진 트리를 사용하는 이진 탐색이라 생각하면 된다.

풀 테이블 스캔(full table scan)

인덱스가 지정되지 않은 테이블을 검색할 때는 풀 테이블 스캔이라 불리는 검색 방법을 사용한다.

테이블의 모든 값을 처음부터 차례로 조사하는 방법으로 1000건의 데이터가 있다면 1000번 값을 비교한다.

이진 탐색(binary search)

차례로 나열된(정렬된) 집합에 대해 유효한 검색 방법이다. 순서대로 모든 값을 검색하는 것이 아니라 집합을 반으로 나누어 조사하는 검색 방법이다.

binary search

만약 책이 한 권 있고 우리가 451페이지를 찾는 방법은?

여러 가지가 있겠지만 그중 우리가 무의식적으로 쓰는 방법을 생각해보면 책의 중간쯤을 펴고 만약 451보다 작은 페이지라면 거기서부터 뒷부분을, 451보다 큰 페이지라면 앞부분을 찾아볼 것이다.

이런 방법을 반복하는 탐색 방법이 이진 탐색이다.

이 방법은 데이터의 양이 늘면 늘수록 풀 테이블 스캔과 검색 횟수가 기하급수적으로 차이가 난다. 데이터의 수가 배로 늘어나더라도 비교 횟수는 1회밖에 안 늘어나기 때문이다.

이진 트리(binary tree)

이진 탐색은 검색 속도가 빠르지만 데이터가 미리 정렬되어 있어야만 사용할 수 있다. 하지만 테이블 내의 행을 언제나 정렬된 상태로 두는 것은 힘들다.

이는 삽입이 발생할 경우에도 매번 재정렬이 필요함을 추측해볼 수 있다.

일반적으로 테이블에 인덱스를 작성하면 테이블 데이터와 별개로 인덱스용 데이터가 저장장치에 만들어진다.

binary tree

트리는 노드(node)라는 요소로 구성되어 있고 트리 중에서 두 개의 가지로 분기하는 구조를 이진 트리라고 한다.

3. 유일성

만약 이진 트리 인덱스 바이너리 내에 같은 값을 가지는 노드가 여러 개 있을 때는 어떻게 하면 될까?

이진 트리에서는 집합 내에 중복하는 값을 가질 수 없다. 노드의 가지는 작은 쪽과 큰 쪽으로만 나누어지고, 같은 값이 있다면 새로운 가지가 필요하기 때문이다.

그러나 이렇게 노드에 같은 값을 가질 수 없다는 키에 대하여 유일성을 가지게 할 경우만 유용하다.

그래서 기본키 제약을 이진 트리로 인덱스를 작성하는 데이터베이스가 많은 것 같다.

데이터베이스에서는 검색 작업이 빈번하게 이루어지는 만큼 검색에 대한 최적화는 성능 향상에 큰 도움을 줄 수 있다.

어떤 열을 기준으로 데이터를 많이 검색하는지 생각해보고 해당 열을 인덱스로 설정한다면 검색을 하는 데 있어서 많은 이점을 가질 수 있을 것이다.


0 개 댓글

답장을 남겨주세요