2012-10-16 3 views
1

몇 가지 결과를 가져오고 효율성에 문제가있는 두 개의 상당히 큰 테이블을 쿼리하려고합니다.비효율적 인 JOIN 방법?

참고 : 관련 열을 포함하여보기 싫은 것처럼 보입니다.

TableA의은 (주) 제품 ID, ownerID을 가지고 있으며, 열

를 계산

TableB의 (소유자) ID, accountHolderID 및 이름 열

난 할 노력하고있어하는 쿼리 TableA의 어디 제품 ID입니다있다 = X는 Stock.productID, Stock.accountHolderID 및 Owners.name을 끌어 올립니다. 이 두 테이블 사이의 관계는 Stock.ownerID = Owners.ID입니다. 그래서 WHERE 조건이 5 개의 productID를 가져 오면 TableA의 ownerID와 일치하는 TableB의 이름이 필요합니다.

이 상황에서 유일한 고유 ID는 내가 INNER 쿼리를 TableB의 물건을 일치 가입 추가 할 때 는

그냥 그 제품에 대한 TableA의에 기본 SELECT 쿼리를 수행하지만 15 초 소요 TableB의

에서 Owners.ID한다 10 분 이상 걸립니다. 나는이 쿼리를 비효율적으로 설계했다고 생각합니다.

SELECT 
Owners.name, 
Stock.productID, 
Stock.ownerID 
FROM Stock 
INNER JOIN 
Owners 
ON Stock.ownerID = Owners.ID 
WHERE 
Stock.productID = 42301679 

어떻게이 쿼리를보다 효율적으로 만들 수 있습니까?

WHERE 조건에 대한 OR을 추가하면 한 번에 여러 제품 ID를 가져올 수 있습니까?

+0

15 초가 긴 것처럼 보입니다. 환경을 물어봐도 될까요? –

+0

꽤 기본적인 쿼리 인 것 같습니다. 테이블의 행 수는 무엇이며, 어떤 인덱스가 있습니까? 또한, 어떤 DBMS를 사용하고 있습니까? (MySQL, 오라클 등). 내 첫 번째 추측은 색인이 누락되었습니다. – Jody

+0

타이밍을 확인하기 위해 기본 SELECT 쿼리를 다시 수행했습니다. 실제로는 9 초입니다. mySQL 환경. Stock 테이블에 21,489,000 개의 항목이 있고 Owners 테이블은 약 439,000입니다. – Jay

답변

1

IN 연산자를 사용하여 한 번에 여러 productIDs을 끌어하기 위해 스키마

을 볼 수 있습니다 보인다 그것은 당신이 owner.id 필드에 매우 중요한 색인을 놓치고있는 것처럼 보입니다. 이제이 인덱스가이 쿼리에 도움이되지만이 인덱스를 추가하는 것이 좋은지 확인하기 위해이 테이블에 대해 실행되는 다른 쿼리를 모두 고려해야합니다.

자주 삽입되는 테이블에 인덱스가있는 29M 행에서는 삽입 시간에 눈에 띄는 영향을 미칠 수 있습니다.

이것은 서로 다른 응용 프로그램이 서로 다른 색인, 즉 OLTP 응용 프로그램과보고 응용 프로그램 (즉, 임시 쿼리를 실행하고있을 수 있음)이 필요한 상황 일 수 있습니다. 일반적인 해결책은이 기능에 맞게 인덱스가 적절하게 조정 된보고/데이터웨어 하우스 쿼리를 실행하는 두 번째 서버를 구축하는 것입니다.

행운을 빈다.

+0

좋은 점 조디. 안타깝게도 Owners 테이블은 데이터베이스의 특성상 업데이트 쿼리가 지속적으로 실시간으로 실행되는 일정한 흐름을 띠고 있습니다. 더 이상 색인을 생성해야한다면 성능 상실이 중요 할 것이라고 생각합니까? 대부분 INSERT가 아닌 쿼리 만 업데이트되지만 다른 행은 변경되지만 ID가 임시 새 ID 이외의 ID가 아닌 경우 ID를 인덱싱하면 그만한 가치가 있습니다. – Jay

+0

인덱스 추가가 성능에 어떤 영향을 미치는지 항상 말하기는 어렵습니다. 업데이트에 삽입에 대한 방법으로 인덱스를 업데이트해야하는지 확실하지 않습니다. 내 제안은 DB를 격리하고 새로운 색인의 유무에 관계없이 일부 벤치마킹 테스트를 실행하고 일반적으로 매우 신중하게 진행되며 이해 관계자의 많은 구매로 진행됩니다. 또한 색인은 가장 효과적이기 위해 두 필드를 모두 포함해야합니다. – Jody

1

Your'e 쿼리는 오른쪽 아마도 우리가 대신 귀하의 의견을 바탕으로 OR

SELECT 
Owners.name, 
Stock.productID, 
Stock.ownerID 
FROM Stock 
INNER JOIN 
Owners 
ON Stock.ownerID = Owners.ID 
WHERE 
Stock.productID IN (42301679,123232,232324) 
+0

오, 저는 IN에 대해 완전히 잊었습니다. 감사합니다 =) – Jay

1

제품 ID가 재고 테이블에서 고유하면 인덱스로 만드는 것이 좋으며 다른 사람이 언급 한 것처럼 성능을 크게 향상시킬 수 있습니다.

특정 길이의 Owner.name 필드를 설정하면 성능이 향상됩니다. mySQL에서 CHAR (32) 열은 이름이 항상 32자를 차지한다는 것을 나타내는 반면 다양한 길이의 문자열에는 VARCHAR을 사용할 수 있습니다. 여분의 미사용 공간은 그냥 채워져 있으므로 (32)를 최대 길이라고 생각할 수 있습니다. 성능상의 이점은 데이터베이스가 각 행이 차지하는 바이트 수를 정확히 알고 있으므로 조회 시간을 향상시키기 위해이 정보를 사용할 수 있다는 점입니다.

+0

슬프게도 productID는 수천 번 사용되는 고유 한 필드가 아닙니다. Owner.name 필드를 잘라내는 것이 가장 좋은 옵션입니다. 감사 – Jay

관련 문제