2010-07-07 5 views
6

이 항목과 관련된 모든 질문은 매우 구체적이며 특정 예제를 중요하게 생각하지만 SQL 최적화의 기본 사항에 관심이있는 것으로 보입니다. 나는 SQL로 작업하는 것이 매우 편하며 하드웨어/저수준 소프트웨어에 대한 배경 지식을 가지고있다.데이터베이스에서 쿼리를 최적화하는 방법 - 기본 사항

내가 원하는 것은 확실한 소프트웨어와 내가 정기적으로보고있는 mysql 데이터베이스를 보는 방법이며, join 문과 where 문 사이의 차이점을 안다.

색인이 왜 도움이되는지 알고 싶습니다. 왜 그런지 알고 싶습니다. 나는 다르게 일어나는 일을 구체적으로 알고 싶습니다. 그리고 저는 어떻게 일어나고 있는지 실제로 볼 수있는 방법을 알고 싶습니다. 나는 SQL의 모든 단계를 망가뜨릴 도구가 필요 없다. 나는 주위를 돌릴 수 있기를 원한다. 누군가가 어떤 칼럼을 색인 할 수 있는지를 알 수 없다면, 나는 종이 한 장을 꺼낼 수있을 것이다. 일정 기간 내에 답변을 찾을 수 있어야합니다.

데이터베이스는 복잡하지만 그다지 복잡하지는 않습니다. 기본 사항을 배우기 위해 훌륭한 자료가 있어야합니다. 그렇기 때문에 발생할 수있는 최적화 문제에 대한 답변을 찾는 방법을 알고 있어야합니다. 포럼에서 정확한 답변.

간결하고 직관적이며 낮은 수준의 너트와 볼트에 도달하는 것을 두려워하지 말고 약간의 수치를 권장하십시오. 나는 온라인 무료 자원을 선호하지만, 도서 추천서가 못을 박는다면 그것을 받아들이는 것을 고려할 것입니다.

답변

6

조건에 따라 모든 조건 및 모든 조인 조건을 조회해야합니다. 둘은 똑같이 작동합니다. 가정하자

우리는

select name 
from customer 
where customerid=37; 

은 어떻게 든 DBMS가 CustomerID를 = 37 기록 또는 기록을 찾을 수있다 물품. 색인이없는 경우이를 수행하는 유일한 방법은 고객 ID를 37과 비교하는 테이블의 모든 레코드를 읽는 것입니다. 하나를 찾았더라도 하나만 있다는 것을 알 수있는 방법이 없으므로 계속 찾고 있어야합니다 다른 사람.

인덱스를 customerid에 만들면 DBMS는 인덱스를 매우 빠르게 검색 할 수 있습니다. 순차 검색이 아니지만 데이터베이스에 따라 이진 검색이나 다른 효율적인 방법이 있습니다. 정확히 어떻게 중요하지는 않지만 순차적 인 것보다 훨씬 빠릅니다. 그런 다음 색인은 해당 레코드 나 레코드로 직접 이동합니다. 또한 인덱스가 "고유"하다고 지정하면 데이터베이스는 하나만 존재할 수 있으므로 초를 찾는 데 시간을 낭비하지 않습니다. (그리고 DBMS 두 번째를 추가 할 수 없습니다.)

지금이 쿼리를 고려해

select name 
from customer 
where city='Albany' and state='NY'; 

이제 우리는 두 가지 조건이있다. 해당 필드 중 하나에만 색인이있는 경우 DBMS는 해당 색인을 사용하여 레코드의 하위 집합을 찾은 다음 순차적으로 검색합니다.예를 들어 상태에 대한 인덱스가있는 경우 DBMS는 NY의 첫 번째 레코드를 빠르게 찾은 다음 city = 'Albany'를 찾아 순차적으로 검색하고 NY의 마지막 레코드에 도달하면 검색을 중지합니다.

"고객 (주, 도시)에 색인 생성"과 같은 두 개의 필드를 모두 포함하는 색인이있는 경우 DBMS는 바로 오른쪽 레코드를 확대/축소 할 수 있습니다.

각 필드에 하나씩 인덱스가 두 개인 경우 DBMS는 적용 할 다양한 규칙을 사용하여 사용할 인덱스를 결정합니다. 다시 말하지만이 작업은 사용중인 특정 DBMS에 따라 다르지만 기본적으로 총 레코드 수, 다른 값의 수 및 값의 분포에 대한 통계를 유지하려고합니다. 그런 다음 다른 조건을 만족하는 레코드를 순차적으로 검색합니다. 이 경우 DBMS는 주보다 많은 도시가 있다는 것을 관찰 할 수 있으므로 도시 인덱스를 사용하여 '알바니'레코드를 빠르게 확대 할 수 있습니다. 그런 다음 순차적으로 검색하여 'NY'에 대한 각 상태를 확인합니다. 캘리포니아 알바니에 대한 기록이있는 경우이 기록을 건너 뜁니다.

모든 가입에는 조회가 필요합니다.

우리가

select customer.name 
from transaction 
join customer on transaction.customerid=customer.customerid 
where transaction.transactiondate='2010-07-04' and customer.type='Q'; 

이제 DBMS가 먼저 읽고 거기에서 해당 레코드를 선택하고 다른 테이블에서 일치하는 레코드를 찾을 수있는 테이블을 결정해야 쓰기 말.

transaction.transactiondate 및 customer.customerid에 대한 인덱스가있는 경우 가장 좋은 계획은이 날짜의 모든 트랜잭션을 찾은 다음 일치하는 고객 ID로 고객을 찾은 다음 확인하는 것입니다 고객이 올바른 유형인지 확인하십시오.

customer.customerid에 색인이없는 경우 DBMS는 신속하게 트랜잭션을 찾을 수 있지만 각 트랜잭션마다 일치하는 고객 ID를 찾는 고객 테이블을 순차적으로 검색해야합니다. (이것은 매우 느릴 수 있습니다.)

대신에 소유 한 색인 만 transaction.customerid 및 customer.type에 있다고 가정합니다. 그런 다음 DBMS는 완전히 다른 계획을 사용할 것입니다. 올바른 유형의 모든 고객에 대해 고객 테이블을 스캔 한 다음 이들 각각에 대해이 고객에 대한 모든 트랜잭션을 찾아 올바른 날짜로 순차적으로 검색합니다.

최적화의 가장 중요한 핵심은 어떤 인덱스가 실제로 해당 인덱스를 도울 것인지를 결정하는 것입니다. 여분의 사용되지 않는 색인은 데이터베이스를 관리하는 데 걸리므로 데이터베이스에 부담이되며 사용하지 않으면 낭비됩니다.

EXPLAIN 명령을 사용하여 주어진 쿼리에 대해 DBMS가 사용할 인덱스를 알 수 있습니다. 나는 내 쿼리가 잘 최적화되고 있는지 또는 추가 인덱스를 작성해야 하는지를 결정할 때이 모든 것을 사용합니다.

주의 사항 : DBMS는 레코드 수와 각기 다른 값의 수 등에 대한 통계를 보관한다는 것을 기억하십시오. 데이터가 변경된 경우 EXPLAIN은 어제보다 완전히 다른 계획을 제공 할 수 있습니다. 예를 들어, 두 테이블을 조인하는 쿼리가 있고이 테이블 중 하나가 매우 작고 다른 테이블이 큰 경우 작은 테이블을 먼저 읽은 다음 큰 테이블에서 일치하는 레코드를 찾는쪽으로 편향됩니다. 테이블에 레코드를 추가하면 더 큰 테이블을 변경할 수 있으므로 DBMS가 계획을 변경하게됩니다. 따라서 실제 데이터가있는 데이터베이스에 대해 EXPLAINS를 시도해야합니다. 각 테이블에 5 개의 레코드가있는 테스트 데이터베이스에 대해 실행하는 것은 실제 데이터베이스에 대해 실행하는 것보다 훨씬 저렴합니다.

음, 훨씬 더 말할 수 있지만, 여기에 책을 쓰고 싶지는 않습니다.

+0

와우, 많은 정보입니다. 감사합니다.이 글을 읽고 몇 가지 사실을 배웠습니다. 즉시 사용하다 – walnutmon

7

다른 도시의 친구를 찾고 있다고 가정 해 봅니다. 한 가지 방법은 집집마다 가서 집이 원하는 집인지 물어보십시오. 또 다른 방법은지도를 보는 것입니다.

색인은 표에 대한 맵입니다. 그것은 당신이 찾고있는 것을 정확히 DB 엔진에게 알려줄 수 있습니다. 따라서 검색해야한다고 생각하는 모든 열을 색인화하고 데이터를 읽는 중이고 빼지 않은 열은 제외하십시오.

좋은 기술적 인 독서 about indicesabout ORDER BY optimization. 정확히 무슨 일이 일어나는지 알고 싶다면 EXPLAIN 문이 필요합니다.

+1

또한 mysql 저속 로그를 관찰 할 가치가 있습니다. http://dev.mysql.com/doc/refman/5.0/en/slow-query-log.html – Pete

+0

인덱스가 조인에 어떻게 영향을 미치는지 특히 관심이 많습니다. 조인을 많이 사용하고 실제로 어떻게 이해하는지 모르겠습니다. 그들은 낮은 수준에서 일합니다. 예를 들어, 서로에 대해 매우 큰 합류를 할 수있는 두 개의 인덱싱 된 열이있는 경우 중요합니까? 조인 공간이 어떻게 할당되고 이동합니까? 둘 다 색인화 된 경우, 둘 다 색인화되지 않으면 어떻게됩니까? – walnutmon

+0

기본적으로 MySQL 매뉴얼 전체 7.2 장이 흥미 롭습니다. 열이 인덱싱되지 않으면 무언가를 찾기 위해 최대 n 개의 비교가 필요합니다. 그렇다면 대부분의 log (n) 비교가 필요합니다. 데이텀의 길이는 분명히 중요한 요소이지만 인덱스가 더 중요합니다. 그러나, 난 거의 정수가 아닌 필드에 가입 절대 찾을. 내 정책은 반복적 인 기회가없는 경우 테이블과 기본 키를 가져야합니다. 그리고 당신의 질문과 같은 "what if"질문은 모델을 만들고 샘플 쿼리에서'EXPLAIN'을 실행함으로써 가장 잘 응답됩니다. – Amadan

2

데이터베이스 최적화에 대해 생각하지 마십시오. 검색어 최적화에 대해 생각해보십시오.

일반적으로 한 케이스를 최적화하여 다른 케이스를 희생합니다. 당신은 당신이에 관심이있는 경우 결정해야합니다.

1

예를 들어

"나는 지수가 어떤 영향을 미칠지에 관심이있어 가입"나는 동등 조인의 경우 할게요 (A FROM SELECT , B WHERE Ax = By).

인덱스가 전혀없는 경우 (이론상 가능하지만 SQL에서는 아닐 것으로 생각합니다) 기본적으로 조인을 계산하는 유일한 방법은 전체 테이블 A를 가져 와서 전체를 파티션하는 것입니다 테이블 y를 만들고 y를 파티션 위로 나눈 다음 파티션을 일치시키고 마지막으로 일치하는 파티션 쌍마다 결과 행을 계산합니다. 가장 작은 테이블을 제외하고는 비용이 많이 들기 때문에 (심지어 메모리 제한 때문에 완전히 불가능할 수도 있습니다).

A 및/또는 B에 색인이 존재하지만 그 중 어떤 색인에도 x resp가 없으면 같은 이야기. y를 첫 번째 속성으로 사용합니다.

x에 인덱스가 있지만 반대로 y가 아닌 경우 다른 테이블이 열립니다. 스캔 테이블 B는 각 행에 대해 값 y를 찾아 인덱스에서 해당 값을 찾아 해당 A를 페치합니다 행을 사용하여 조인을 계산합니다.더 이상의 다른 제한 사항이 적용되지 않으면 (AND z = ...) - x와 y 값 사이에 일치가 거의없는 경우를 제외하고는 여전히 많은 이점을 얻지 못할 것입니다.

x와 y 모두에 정렬 된 인덱스 (해시 기반 인덱스가 정렬되지 않은 경우)가있는 경우 세 번째 가능성이 열립니다. 인덱스 자체에서 일치하는 검색 수행 (인덱스 자체가 테이블보다 작을 수 있음) 따라서 인덱스 자체를 스캔하는 데 더 짧은 시간이 걸릴 것입니다.), 일치하는 x/y 값의 경우 해당 행의 조인을 계산하십시오.

기본 사항입니다. x> y 등의 조인에 대한 변형이 발생합니다.

1

MySql 도구에 대해서는 잘 모르겠지만 MS SqlServer에는 쿼리가 수행 할 모든 작업과 전체 처리 시간을 보여주는 도구가 있습니다. 쿼리가 걸립니다.

이 도구를 사용하면 옵티마이 저가 수행하는 것이 도움이 될 수 있다고 생각하기 때문에 쿼리 최적화 프로그램에서 쿼리를 최적화하는 방법을 이해하는 데 많은 도움이되었습니다. 쿼리를 수정하고 밑줄 친 데이터베이스를 수정하여 각 변경이 쿼리 계획에 어떻게 영향을 미치는지 확인할 수있었습니다. 서면 작성에는 몇 가지 중요한 요지가 있지만 내게는 귀하가 이미 그렇게 생각하는 것이 귀하의 경우에 최적화되어있는 것처럼 보입니다. 일반적인 규칙보다 훨씬 더 중요합니다. 몇 년 동안의 DB 개발을 통해 SQL Server에서 데이터베이스 최적화를 겨냥한 몇 권의 책을 살펴본 결과 유용한 정보가 거의 발견되지 않았습니다.

빠른 검색 결과는 이와 비슷한 도구처럼 들리는 http://www.mysql.com/products/enterprise/query.html입니다.

이것은 물론 쿼리 수준 이었지만 데이터베이스 수준 최적화는 다시 물고기와 다른 주전자이지만 데이터베이스가 하드 드라이브 등으로 나뉘는 방법과 같은 매개 변수를보고 있습니다. 적어도 SqlServer에서는 테이블을 다른 hdd 및 심지어 디스크 플레이트로 나누기 위해 선택하십시오. 드라이브 및 드라이브 헤드가 병렬로 작동 할 수 있기 때문에 큰 효과가 있습니다. 데이터베이스를 여러 스레드와 프로세서에서 병렬로 실행할 수 있도록 쿼리를 작성하는 방법도 있지만,이 두 가지 문제는 다시 데이터베이스 엔진과 사용중인 버전에 따라 달라집니다.

관련 문제