출처 : http://noritersand.tistory.com/156

 


출처 :  http://blog.naver.com/PostView.nhn?blogId=waws01&logNo=60181424769&redirect=Dlog&widgetTypeCall=true



★ Best 실행계획은 Clustered Index Seek (Clustered) 이다!!!



====================================================================================

CREATE TABLE tmp_myfan

(

     fan_id   INT          NOT NULL                                           -- 고유값

   , fan_name NVARCHAR(20) NOT NULL                                           -- 날조아하는여학생명

   , fan_feel FLOAT        NOT NULL DEFAULT 0                                 -- 호감지수

   , fan_gift NVARCHAR(30)     NULL                                           -- 그녀들이내게한선물

   , fan_date VARCHAR(8)   NOT NULL DEFAULT CONVERT(CHAR(8), GETDATE(), 112)  -- 선물받은날짜

   , cr_date  DATETIME              DEFAULT GETDATE()                         -- 입력날짜

);

CREATE UNIQUE CLUSTERED INDEX ix_tmp_myfan ON tmp_myfan(fan_id, cr_date);  

====================================================================================




1) SELECT절과 WHERE절에 CLUSTERED INDEX 컬럼인 경우

====================================================================================

SELECT fan_id, cr_date FROM tmp_myfan WHERE fan_id = 110 ;

====================================================================================

=> 실행계획 : Clustered Index Seek (Clustered)


2) SELECT절에는 CLUSTERED INDEX 컬럼, WHERE절에는 index가 아닌 컬럼인 경우

====================================================================================

SELECT fan_id FROM tmp_myfan WHERE fan_feel > 95;

====================================================================================

=> 실행계획 : Clustered Index Scan (Clustered)     <-- 사실상 Table Scan과 다를 바가 없다고 함.


3) SELECT절에는 CLUSTERED INDEX 컬럼, WHERE절에는 index 컬럼인 경우

====================================================================================

CREATE INDEX ix_non_tmp_myfan ON tmp_myfan(fan_feel); -- fan_feel 컬럼에 인덱스 생성

SELECT fan_id FROM tmp_myfan WHERE fan_feel > 95;

====================================================================================

=> 실행계획 : Index Seek (NonClustered)


4) fan_feel에 인덱스 생성하고 4-1, 4-2의 경우

   4-1) 

   =================================================================================

   CREATE INDEX ix_non_tmp_myfan ON tmp_myfan(fan_feel); -- fan_feel 컬럼에 인덱스 생성


   SET SHOWPLAN_ALL ON

   SELECT fan_feel FROM tmp_myfan WHERE fan_feel > 95 AND fan_id = 110;

   SET SHOWPLAN_ALL OFF


   |--Clustered Index Seek(OBJECT:([Test].[dbo].[tmp_myfan].[ix_tmp_myfan]), 

   SEEK:([Test].[dbo].[tmp_myfan].[fan_id]=(110)),  

   WHERE:([Test].[dbo].[tmp_myfan].[fan_feel]>(9.400000000000000e+001)) ORDERED FORWARD)

   =================================================================================

   => 해석 : ix_tmp_myfan 를 WHERE 순서를 무시하고 Clustered Index Seek 로 수행하고, 그때 행하고 ix_non_tmp_myfan 의 fan_feel는 필터링. 사실상 Seek시 범위를 줄여주지 못하는 상황.


   4-2) (4-1에 이어서..)

   =================================================================================

   SET SHOWPLAN_ALL ON



   |--Index Seek(OBJECT:([Test].[dbo].[tmp_myfan].[ix_non_tmp_myfan]), 

   SEEK:([Test].[dbo].[tmp_myfan].[fan_feel] > (9.800000000000000e+001)),  

   WHERE:([Test].[dbo].[tmp_myfan].[fan_id]>(110)) ORDERED FORWARD)

   =================================================================================

   => 해석 : ix_non_tmp_myfan 를 Index Seek 로 수행하고, 그때 행하고 ix_tmp_myfan 의 fan_id는 필터링. 역시나 데이터량이 많은 경우라면 특단의 조치가 필요한 상황.


5) fan_feel에 인덱스 생성하고 다음의 경우

====================================================================================

CREATE INDEX ix_non_tmp_myfan ON tmp_myfan(fan_feel); -- fan_feel 컬럼에 인덱스 생성


SET SHOWPLAN_ALL ON

SELECT fan_feel FROM tmp_myfan WHERE fan_feel = 99 AND fan_id > 110;

SET SHOWPLAN_ALL OFF



|--Index Seek(OBJECT:([Test].[dbo].[tmp_myfan].[ix_non_tmp_myfan]), 

SEEK:([Test].[dbo].[tmp_myfan].[fan_feel]=CONVERT_IMPLICIT(float(53),[@1],0) 

AND [Test].[dbo].[tmp_myfan].[fan_id] > CONVERT_IMPLICIT(int,[@2],0)) ORDERED FORWARD)

====================================================================================

=> 해석 : 아주 Best한 결과!! 

ix_non_tmp_myfan 를 Index Seek 로 수행할 때 ix_tmp_myfan 의 fan_id 를 NON LEAF LEVEL에 포함시켜 버린다. 

NONCLUSTERED INDEX 가 NON UNIQUE하고 포함된 COLUMN이 WHERE 절에서 등호(=)로 조회할때 

위와 같이 CLUSTERED INDEX CLUSTERING KEY가 NONCLUSTERED INDEX 의 NON LEAF LEVEL에 포함되게 된다.



6) SELECT 절에 index가 아닌 fan_name을 추가하여 조회한 경우

====================================================================================

SELECT fan_id, fan_name FROM tmp_myfan WHERE fan_feel > 95;

====================================================================================

=> 실행계획 : Clustered Index Scan (Clustered)

=> 해석 : fan_name과 같이 필요없는 컬럼을 함부로 조회하게 되면, 성능이 급격하게 저하된다.




 
 
- 참고: https://madplay.github.io/post/difference-between-dollar-sign-and-sharp-sign-in-mybatis
- 참고: https://rh-cp.tistory.com/71
- 참고: https://logical-code.tistory.com/25
 
■ mybatis #과 $의 차이
- #을 사용하면, Prepared Statement를 의미한다. 변수 값이 바뀌더라도 같은 쿼리로 인식되어 재활용되기 때문에 성능에 유리하다. 그리고 변수 값 양쪽에 자동으로 따옴표(')가 붙기 때문에 SQL Injection을 방어할 수 있다.
- $를 사용하면, 일반 Statement를 의미한다. 변수 값이 바뀔 때마다 다른 쿼리로 인식되어 새로 파싱 과정을 거치기 때문에 성능에 불리하다. 그리고 변수 값이 그대로 반영되어 SQL Injection에 취약하다. 테이블명이나 컬럼명을 넘겨 받아야 하는 용도 정도로만 사용하면 된다.

 

+ Recent posts