2022년 9월 26일 월요일

SQL - 초급 교육

 

. (주)씨퀄로 : http://www.sqlroad.com

. SW개발 : http://www.sqlroad.com/080819-2/ (SQLBigEyesHammer V3 Freeware)


. 은행쿼리 : 22GB -> 0.1MB (218,000배 향상) : where : 함수 X


1. 실행계획 (인덱스 사용 여부)

2. 세션옵션 (IO) (테이블 단위 페이지 IO량 확인)


. 실제 실행계획 : 검색, seek (OK)

. 논리적 읽기, lob 논리적 읽기

. lob (Large Object) : text, image, ....


. ANSI 표준 사용하기

. WHERE 절 작성 순서는 성능과 연관?

   - 옵티마이저가 변경하기 때문에 순서는 성능과 무관하다.

   - inner join 일 경우에 해당

. 쿼리문 작성 시 테이블 이름 선언할 때 전체 이름으로 (예 db.schema.object)

   - schema 생략 시 옵티마이저가 ID 찾아 사용

. 날짜 그 날 마지막 시간 20211010 23:59:59.997

. between '20211010' and '20211010 23:59:59.99?'

. >= '20211010' and < '20211011'

. 문자열 비교 시 오른쪽 공백은 고려하지 않는다 (rtrim 안해도 된다)

  - @varchar, @char

. MSSQL 다른 DB와 다른 것은 잠금(Lock) 부분이 다르게 적용됨

. 의미 오류 (Semantic Error) : 불필요한 조건

  - WHERE PK_Col IS NULL

  - WHERE ShipVia > 4 OR ShipVia > 2  (false)

  - DISTINCT PK_Col, ....

  - LIKE 'aaa'

  - EXISTS (SELECT DISTINCT.... FORM ...   무조건 1개만 있으면 작업 끝난다)  

  - ORDER BY PK_Col 

  - LIKE '%'

  - HAVING (WHERE에 있어야 할 조건 경우)

  - select 50 orderid from orders (별칭 붙이는 습관이 있어야 함)

  

2. SARG (검색인수)

. WHERE, FROM, HAVING : TRUE, FALSE, UNKNOWN

. 검색 대상 및 범위를 제한할 수 있는 식

. 인덱스 사용 및 쿼리 최적화를 위한 필요 조건

. 반대적인 조건 사항 : Non-SARG (비 검색인수)

  - 불필요한 데이터 (열,행) 요청

  - 열 간 비교 (컬럼 대 컬럼)

  - 부정문은 긍정문으로 자동 변환 (범위 검색이 된다)

  - ID IN (2,4,6) --> ID = 2 or ID = 4 or ID = 6

  - NOT IN (가능한 사용하지 말자)

  - 복합 Index 선행 열 ( "=" 조건이 제일 먼저 나오게 해야 한다)

     ex. PK = (사업장 + 주문일자 + 주문번호)

          사업장 LIKE '%' and 주문일자 = '20211011'     

(예)

PK (사업자, 일자, 번호)

WHERE 일자 = ?

         사업자 LIKE ?

         번호 = ?

사업장 만 Seek, 나머지는 스캔 (인덱스 사용 못 함)


*** 쿼리 스토어 기능 권장 (성능관리) ver 2017 이상

 

. WHERE 함수 (가급적 사용 X)

. WHERE SUBSTRING(CustomerID, 1, 3) = 'CEN' --> WHERE CustomerID LIKE 'CEN%'

. WHERE CONVERT(varchar(8), OrderDate, 112) = '19960704' --> WHERE OrderDate >= '19960704' AND OrderDate < '19960705'

. WHERE DateDiff(dd, ShippedDate, '19980506') <= 1 --> WHERE ShippedDate >= DATEADD(dd, -1, '19980506')

. MSSQL은 NULL 값 인덱스 값으로 저장된다. 

. WHERE ISNULL(OrderDate, '19970702') = '19970702' --> WHERE (OrderDate = '19970702' OR OrderDate IS NULL)


*** ORM 파라미터 : WHERE col = @id 대부분 유니코드('N')로 인식 함.  (예) NVARCHAR 


. LIKE : 문자열에만 사용, %???% (앞에 % 있으면 안된다)

. 열 간 비교

   - select emlid, ship from orders where emlid = ship and ship = 2

   - where emlid = case @ship is null then emlid else @ship end


. OR 인덱스 안 걸리면  --> UNION 으로 변경


3. 조건절 상수화 이슈

. WHERE OrderID > @ID 

  - 상수화 할 수 있어야 옵티마이저가 실행계획을 예측 가능하게 된다.

  - 쿼리 컴파일 시점에 @ID 값을 알아야 하기 때문

  - 문제되는 조건

     . 로컬변수 declare @id int .... where OrderId > @ID

     . 사용자 정의 함수 where OrderId > dbo.uf_OrderNo()

     . 테이블 변수 성능 문제 (@table --> #Table 로 사용)

  - MSSQL 2019 이상 EE "Scalar UDF InLine" 자동 튜닝 지원 (아직 시작 단계. 안정화 진행 중)

  

  - 집합연상 WHERE aaa in (select distinct.....) distinct 할 필요 없다. 중복 자동 제거 됨.

  - where a.ordrid = dbo.uf_split('1,2,3,4,..') -->  join order as a on a.ordrid = dbo.uf_split('1,2,3,4,..')

  - NOLOCK 사용 시 ORDER BY 생략 시 문제 발생할 수 있음 (데이터 정합성 고려)

  - ORDER BY 작성 시 유니크한 값이 나오도록 조건을 만들어야 한다.

     . select top 5 .... ORDER BY aaa, bbb, ccc....

  - count(*) vs count(열) --> null 값이 허용된 경우 count(열)

  - count(*) vs exists --> 데이터 존재 여부 경우 exists

  - 집계 시 대량의 null 이 있을 경우 is not null 처리

  - union --> 자동으로 distinct 처리하는 결과로 처리 (옵티마이저 판단)

  - union all --> 전체 데이터 처리

  - 채번을 원 쿼리로 : update 채번 set @일련번호 = 일련번호 = 일련번호 + 1 where ....

  - OUTPUT inserted.*, deleted.*


4. JOIN

(1) 네스티드 루프 조인

(2) 해쉬 조인

(3) 머지 조인


- 네스티드 루프 조인

  . 첫번째 검색 테이블 데이터가 적어야 함. (inner join 인 경우)

  . 데이터가 많은 FK에 값 convert 할 경우 --> 첫번째 PK 값을 convert 하는 것이 좋다.

  . outer join 시 옵티마이지 처리에 어려울 수 있다. 테이블 순서는 상관없다.

  . 나름 기준을 잡아서 테이블 순서를 정하자. (필수 아님)


5. Subquery 이해

. 파생 테이블 : 외곽 테이블의 key 값이 자동으로 안쪽 파생 테이블 필터링 조건에 적용 된다.

. case select... (X) --> select case (O) 

. null 값이 없도록 : where customerID not in (select customerID from orders where customerID is not null)

. CTE

  - 성능 튜닝 어렵다

. 쿼리 힌트

. 잠금 튜닝

  - 조회 전용 쿼리 시 잠금 차단 회피

     . table WITH (NOLOCK) : 수정 중인 데이터 값을 가지고 온다. (권장 안함 X. 수정후 데이터를 넘긴다)

     . Read Committed Snapshot 사용 권장 O (내부적으로 데이터를 스냅샷 하여 그 데이터를 넘겨준다)

         - TempDB 사용할 시 때문에 해당 TempDB 관리 필요.


6. Cursor : 되도록 운영을 위한 사용 하시고 서비스용은 최대한 사용하지 말 것

   - 사용한다면

     . LOCAL

     . FAST_FORWARD or STATIC READONLY FORWARD_ONLY


7. 함수

  - InLine Table-Values Function (권장)





javascript - SQL 예약어 제거

  <script language="javascript"> //특수문자, 특정문자열(sql예약어) 제거 function checkSearchedWord(obj){ obj.value = obj.value+&quo...