2016-06-17 3 views
0

두 개의 테이블이 있습니다. 나는 표 2에있는 표 1의 모든 행을 찾고 되돌아 가고 싶습니다. 나는 대답했다. 그러나 나는 그것을 더 빨리 원한다. 예 :최적화 - SQL : 여러 테이블에 모든 데이터를 표시하는 방법

Create table One (ID INT, Value INT, location VARCHAR(10)) 
Create table Two (ID INT, Value INT, location VARCHAR(10)) 

INSERT INTO One VALUES(1,2,'Hanoi') 
INSERT INTO One VALUES(2,1,'Hanoi') 
INSERT INTO One VALUES(1,4,'Hanoi') 
INSERT INTO One VALUES(3,5,'Hanoi') 

INSERT INTO Two VALUES(1,5,'Saigon') 
INSERT INTO Two VALUES(4,6,'Saigon') 
INSERT INTO Two VALUES(5,7,'Saigon') 
INSERT INTO Two VALUES(2,8,'Saigon') 
INSERT INTO Two VALUES(2,8,'Saigon') 

과 답변 :이 쿼리와

SELECT * FROM One WHERE ID IN (SELECT ID FROM Two) 
UNION ALL 
SELECT *FROM Two WHERE ID IN (SELECT ID FROM One) 

, 시스템은, I 시스템이 한 번 (두 번 테이블 하나를 테이블을 스캔하고자하는 테이블 4 번 enter image description here

를 스캔 테이블 두 번).

나는 미친가요?

+1

음 .. 그것은 다릅니다. 우선 IN 대신 EXISTS를 사용합니다. 둘째, 적절한 색인을 구현할 것입니다. – DNac

+1

두 테이블간에 ID에 대한 내부 조인을 수행 할 수 없습니까? – DB101

+0

죄송합니다. 내 영어가 너무 안좋아. 나는 질문을 고정시켰다. 우리는 –

답변

0

당신은 같은 것을 시도 할 수 있습니다 :

-- CREATE TABLES 
IF OBJECT_ID ('tempdb..#One') IS NOT NULL 
DROP TABLE #One; 

IF OBJECT_ID ('tempdb..#Two') IS NOT NULL 
DROP TABLE #Two; 

CREATE TABLE #One (ID INT, Value INT, location VARCHAR(10)) 
CREATE TABLE #Two (ID INT, Value INT, location VARCHAR(10)) 

-- INSERT DATA 
INSERT INTO #One VALUES(1,2,'Hanoi') 
INSERT INTO #One VALUES(2,1,'Hanoi') 
INSERT INTO #One VALUES(1,4,'Hanoi') 
INSERT INTO #One VALUES(3,5,'Hanoi') 

INSERT INTO #Two VALUES(1,5,'Saigon') 
INSERT INTO #Two VALUES(4,6,'Saigon') 
INSERT INTO #Two VALUES(5,7,'Saigon') 
INSERT INTO #Two VALUES(2,8,'Saigon') 
INSERT INTO #Two VALUES(2,8,'Saigon') 

-- CREATE INDEX 
CREATE NONCLUSTERED INDEX IX_One ON #One (ID) INCLUDE (Value, location) 
CREATE NONCLUSTERED INDEX IX_Two ON #Two (ID) INCLUDE (Value, location) 


-- SELECT DATA 
SELECT o.ID 
     ,o.Value 
     ,o.location 
FROM #One o 
WHERE EXISTS (SELECT 1 FROM #Two t WHERE o.ID = t.ID) 

UNION ALL 

SELECT t.ID 
     ,t.Value 
     ,t.location 
FROM #Two t 
WHERE EXISTS (SELECT 1 FROM #One o WHERE t.ID = o.ID) 

을 그러나 당신이 얼마나 "큰"데이터를 따라 달라집니다. 데이터가 매우 크고 (수백만 행) SQL Server Enterprise 버전을 실행중인 경우 columnstore indexes을 사용할 수 있습니다.

+0

감사합니다. 나는 컬럼 스토어 인덱스를 연구 할 것이다. –

+0

ColumnStore 인덱스가 여기에 적용될지는 모르겠습니다. 아마도'ID' 필드에 대한 일반적인 색인으로 충분할 것입니다. 열 저장소는 많은 양의 데이터를 저장하는 데 적합하지만 ('수백만은 대부분의 시스템에서 작은 변화'이지만) 선택 쿼리를 느리게 만드는 부작용이 있습니다. 이 경우 중복이없는 ID 필드에 큰 구멍이 있다고 가정하면 columnstore는 일반적인 인덱스보다 스캔 할 때 더 많은 노력이 필요할 수 있습니다. 또한 데이터를 수정할 필요가있을 때 columnstore에 더 많은 오버 헤드가 발생합니다 !! 여기에 문제가 될 수도 있고 없을 수도 있습니다. 내 2 센트. – deroby

0

테이블을 두 번 스캔하는 이유는 테이블 X에서 읽고 테이블 Y에서 해당 값을 조회하기 때문입니다. 끝나면 테이블 Y부터 시작하여 일치 항목을 찾습니다. 표 Y. 그 후, 두 결과가 결합되어 호출자에게 리턴됩니다.

비록 테이블이 넓고 많은 열을 포함하고 있지 않다면 좋은 이유가없이 많은 IO를 수행하고 있지만 그것은 나쁜 것이 아닙니다. 또한 예제에서 ID 필드에 '논리'가 없으므로 다른 테이블에서 일치하는 ID를 찾는 데는 전체 테이블을 검색해야합니다. 단순히 값의 목록입니다. 사물의 속도를 높이려면 ID 필드에 색인을 추가해야 시스템이 특정 ID 값을 훨씬 빨리 찾을 수 있습니다. 또한 조회 단계에서 읽어야하는 데이터의 양도 제한됩니다. 서버는 ID 값 (**) 만 포함하고 다른 모든 불필요한 필드는 읽지 않습니다.

솔직히 말하면, 나는 당신의 요구 사항이 약간 이상하다고 생각하지만, 여기에 대해서는 이해가 쉽도록 단순화가 필요하다고 생각합니다. 내 첫 반응은 두 테이블간에 JOIN을 사용하라는 제안 이었지만 ID 필드가 고유하지 않기 때문에 중복 된 결과가 나타납니다! 이 문제를 해결하기 위해 DISTINCT을 추가했지만 그 후에는 심각하게 느려졌습니다. 결국 WHERE ID IN (...)을 수행하는 것이 가장 효율적인 방법으로 밝혀졌습니다. ID 필드에 인덱스를 추가하면 예상보다 큰 영향을 미치지는 않았지만 예상보다 빠른 속도를 보였습니다. 아마도 다른 필드가 거의없고 입출력에서의 이득이 무시할 만하다. (읽기 : 5 백만 행).

FYI : 개인적으로 나는 개인적으로 WHERE IN (...) 이상의 구조 WHERE EXISTS()을 선호하지만 둘 다 동일하며 사실 동일한 쿼리 계획을 실제로 만들어 냈습니다.

(** : 인덱스 된 필드를 제외하고 모든 인덱스에는 일반적으로 리프 데이터의 테이블 필드의 기본 키인 클러스터 된 인덱스도 포함되어 있습니다 .. 자세한 내용 Kimberly L. Tripp에는 인덱스에 대한 흥미로운 기사가 ​​있습니다 어떻게 작동하는지.)

관련 문제