RDBMS에서 "인덱스"란 무엇입니까? [닫은]


21

대부분의 개발자가하는 것처럼 (주로 ... 음! 인덱스) 인덱스를 사용하지만 인덱스를 사용하여 데이터베이스를 최적화하는 미묘한 방법이 많이 있습니다. DBMS 구현과 관련이 있는지 확실하지 않습니다.

내 질문은 : 인덱스를 사용하는 방법에 대한 좋은 예는 무엇입니까 (기본, 명백한 경우 제외), 테이블에서 인덱스를 지정할 때 DBMS가 데이터베이스를 어떻게 최적화합니까?


이 질문에 대한 추가 생각에서이 질문은이 사이트에 너무 일반적입니다. 적절할 수있는 질문의 범위를 변경하면이 질문은 사이트에 적합하지 않습니다.
jcolebrand

라이브러리 메타포 mysqlperformanceblog.com/2011/08/30/…를 사용하여 인덱스를 설명하고 싶습니다 . 도움이되는지 확인하십시오.
Jonathan

답변:


11

색인을 "목차"로 생각하십시오. 이것은 파일의 위치에 대한 포인터 목록 (일명 오프셋)입니다. 일치하는 기준에 대해 테이블을 검색하는 대신 테이블에 수백만 개의 레코드가 저장되어 있다고 가정하면 일치하는 순서로 정렬 된 목록을 참조한 다음 포인터를 특정 일치하는 행에 스택하는 것이 훨씬 빠릅니다. 인덱스의 완벽한 예는 테이블 기본 키 필드, 가장 일반적으로 "id"필드입니다. 행 ID # 11234566을 원하는 경우 위치 11234566에 대한 데이터 소스를 스캔하는 것보다 인덱스에 데이터에 대한 포인터를 요청하는 것이 훨씬 빠릅니다.

인덱싱을 그렇게 명확하게 사용하지는 않습니다.

CREATE TABLE activity_log (
id INT UNSIGNED NOT NULL AUTO_INCREMENT,
activity_type_id SMALLINT UNSIGNED NOT NULL,
datetime_created DATETIME
KEY(activity_type_id),
PRIMARY KEY(id)
);
CREATE TABLE activity_log_to_date_key (
activity_log_id INT UNSIGNED NOT NULL,
date_created_key  INT UNSIGNED NOT NULL REFERENCES dim_datetime(id),
UNIQUE KEY(activity_log_id),
KEY(date_created_key)
);
CREATE TABLE dim_datetime (
id INT UNSIGNED NOT NULL AUTO_INCREMENT,
date_hour DATETIME NOT NULL,
PRIMARY KEY(id),
KEY(date_hour)
);

작업을 수행하면 로그 레코드가 생성되지만 로그 테이블보다 검색 / 정렬이 더 빠른 인덱스 된 날짜 시간에 대한 참조를 만들 수 있습니다. 그런 다음 고유 한 기본 키로 로그 테이블을 다시 결합하십시오. 이것을 확장해야한다면 알려주십시오. 이것이 의미가 있기를 바랍니다.

샘플 쿼리 :

SELECT a.activity_log_id, al.activity_type_id, al.datetime_created
FROM activity_log_to_date_key a 
INNER JOIN dim_datetime d ON (d.id = a.date_created_key)
LEFT JOIN activity_log al ON (al.id = a.activity_log_id)
WHERE d.date_hour BETWEEN '2009-01-01 00:00:00' AND '2009-06-01 12:00:00';

고마워, 그것은 매우 분명하다! 귀하의 예에서 "PRIMARY"는 RDMBS가 "오프셋"을 저장하는 방식을 변경합니까, 아니면 고유성 제한 조건에 사용됩니까?
토마스 줄린

9

많은 사람들이 놓친 것처럼 보이는 한 가지 점은 DBMS가 쿼리에서 테이블 참조 당 하나의 인덱스 만 사용하는 경우가 많거나 가능할 수 있다는 것입니다. 여러 인덱스를 사용할 수 있고 사용하는 경우 결합 된 데이터를 사용하는 것이 더 빠를 것입니다 존재하는 경우 색인.

예를 들어, 큰 테이블에서 행을 검색하는 경우 WHERE AnIntegerColumn = 42 AND AnOtherInt = 69해당 행으로 가장 빠른 경로는 AnIntegerColumn 및 AnOtherInt라는 두 열의 인덱스입니다. 각각의 인덱스 만 있고 결합 된 인덱스는없는 경우 DB는 하나 또는 다른 인덱스를 검색하고 결과를 두 번째 절로 개별적으로 필터링하거나 두 가지를 모두 스캔 한 후 결과를 결합합니다.

복합 인덱스를 사용하여 개선 할 수있는 또 다른 일반적인 간단한 작업은 WHERE SomeColumn = <SomeValue> ORDER BY SomeOtherColumnSomeColumn 및 SomeOtherColumn에 인덱스가있는 경우 (올바른 순서로) 필터링 및 순서 지정 작업을 일부 상황에서 동시에 수행 할 수 있습니다.

인덱스를 저장하는 데 사용되는 추가 공간 (및 DB에서 쓰기 작업이 많은 경우 인덱스를 유지하기위한 IO로드)이 약간 덜 최적화 된 읽기 쿼리보다 더 나쁜 문제 일 수 있으므로 너무 많은 인덱스를 추가하면 물론 최적화가 좋지 않을 수 있습니다. 과도하게하지 마십시오.


2

David와 Randy는 이것에 대해 설명했습니다. 난 그냥 것을 추가하고 싶었 명령은 당신이 큰 인덱스를 만들뿐만 아니라, 인덱스가 필요로하는 제안 밖으로 저장 얻을 것이다 때 파악에 큰 도움이 될 수 있습니다. 데이터베이스가 쿼리를 실행하기 위해 수행하는 단계를 표시하므로 시간이 가장 오래 걸리는 비트를 알 수 있습니다.EXPLAIN


Gaurav의 답변에 추가하려면 "EXPLAIN EXTENDED"를 사용한 다음 즉시 "SHOW WARNINGS"를 입력하여 쿼리가 어떻게 번역되는지 확인하십시오.
랜덤

1

내가 아직 여기에 언급하지 않은 것은 하나 이상의 디스크가있을 때 데이터가 실제로있는 곳과 다른 디스크에 색인을 넣고 싶을 것입니다. 일부 작업 속도가 빨라질 수 있습니다. 나는 이것이 그 자체로 의문의 가치가 있다고 생각합니다.


사실 이었지만 요즘에는 I / O 하위 시스템을 추측하려고하지 않습니다. 스토리지 배열이 데이터를 어디에 배치할지 알 수 없습니다.
Gaius

1
@gaius 차라리 RAID5 (또는 이와 유사한) 설정이없는 경우 E :, F : 등의 데이터에 인덱스를 넣습니다.
jcolebrand
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.