use-the-index-luke

2.7-3 Combining Columns

kim-jiyoung 2023. 8. 28. 21:45

use-the-index-luke 저자 Markus Winand

---------------------------------------------

Markus Winand는 SQL에 대한 통찰력을 제공하고 다양한 시스템이 SQL을 지원하는 방법을 modern-sql.com 에서 보여줍니다. 이전에 그는 use-the-index-luke.com 을 만들었는데, 지금도 활발하게 유지되고 있습니다. Markus는 winand.at 를 통해 강사, 연사 및 컨설턴트로 고용될 수 있습니다.

---------------------------------------------

You can upload a Korean translation of use-the-index-luke.com on your blog

Thank you from the bottom of my heart to author Makus Winand for allowing me.

 

These are translations that I use for studying by using a papago (google translate)

The translations may not be correct or there may be a typo.

I'd appreciate it if you could point it out in the comments.

---------------------------------------------

---------------------------------------------

use-the-index-luke.com 의 한글번역본을 블로그에 업로드 해도 된다고

허락해주신 Makus Winand 저자님께 진심으로 감사합니다.

 

이 번역본들은 제가 공부용도로 번역기(papago, google transrate)를 돌려서 

번역한 내용들이라 맞지 않거나, 오타가 있을수 있습니다.

댓글로 지적해주시면 감사하겠습니다.

---------------------------------------------

 

https://use-the-index-luke.com/sql/where-clause/obfuscation/concatenation

결합

 

섹션에서는 연결된 인덱스에 영향을 미치는 일반적인 난독화에 대해 설명합니다.

번째 예는 날짜와 시간 유형에 대한 것이지만 반대입니다.

다음 MySQL 쿼리는 날짜와 시간 열을 결합하여 다에 범위 필터를 적용합니다.

----------------------------------------------------------

SELECT ...
  FROM ...
 WHERE
ADDTIME(date_column, time_column)
     > DATE_ADD(now(), INTERVAL -1 DAY)

----------------------------------------------------------

지난 24 시간 동안의 모든 레코드가 선택됩니다.

검색이 인덱싱된 열이 아니라 파생된 데이터에 대해 수행되기 때문에 쿼리가(DATE_COLUMN, TIME_COLUMN) 연결된 인덱스를 제대로 사용할 없습니다.

 

날짜 시간 구성 요소를 모두 포함하는 데이터 유형(: MySQL DATETIME) 사용하여 문제를 방지할 있습니다. 그런 다음 함수 호출 없이 열을 사용할 있습니다.

----------------------------------------------------------

SELECT ...
  FROM ...
 WHERE
datetime_column
     > DATE_ADD(now(), INTERVAL -1 DAY)

----------------------------------------------------------

안타깝게도 문제에 직면했을 테이블 변경할 없는 경우가 많습니다.

 

데이터베이스가 지원하는 경우 다음 옵션은 Function Based INDEX입니다. 이전에 설명한 모든 단점이 있습니다. MySQL 사용할 Function Based INDEX 옵션이 아닙니다.

 

데이터베이스가 DATA_COLUMN,TIME_COLUMN 연결된 인덱스와 access predicate(적어도 부분적으로) 사용할 있도록 쿼리를 작성할 있습니다.

이를 위해 DATE_COLUMN 추가 조건을 추가합니다.

----------------------------------------------------------

 WHERE ADDTIME(date_column, time_column)
     > DATE_ADD(now(), INTERVAL -1 DAY)
  
AND date_column
    >= DATE(DATE_ADD(now(), INTERVAL -1 DAY))

----------------------------------------------------------

 

조건은 절대적으로 중복되지만 DATE_COLUMN

스트레이트 필터로 access predicate 사용할 있습니다. 기법은 완벽하지는 않지만 대개 충분히 근사합니다.

----------------------------------------------------------

Tip

범위 조건이 여러 열을 결합하는 경우 가장 유의한 열에 중복 조건을 사용합니다.

 

PostgrSQL 이면, 구문을 사용하는 것이 좋습니다.

----------------------------------------------------------

날짜와 시간을 텍스트열에 저장할 때도

방법을 사용할 있지만, ISO 8601(YYYY-MM-DD HH:MM:SS)에서 제안한 것처럼 사전 정렬시 시간순으로 정렬되는 날짜와 시간 형식을 사용해야 합니다.

다음 예제에서는 Oracle 데이터베이스의 TO_CHAR 함수를 사용합니다:

----------------------------------------------------------

SELECT ...
  FROM ...
 WHERE date_string || time_string
     > TO_CHAR(sysdate - 1, 'YYYY-MM-DD HH24:MI:SS')
  
AND date_string
    >= TO_CHAR(sysdate - 1, 'YYYY-MM-DD')

----------------------------------------------------------

“Paging Through Results” 섹션에서 다시 여러열에 범위 조건을 적용하는 문제에 대해 설명합니다.

또한 이를 완화하기 위해 동일한 접근 방법을 사용할 입니다.

 

경우에 따라 반대의 경우가 발생하여 조건을 의도적으로 난독화하여 이상 access predicate 사용할 없게 하려는 경우가 있습니다 바인딩 매개 변수가 LIKE 조건에 미치는 영향에 대해 논의할 이미 문제를 살펴보았습니다. 다음 예시를 생각해 보십시오.

----------------------------------------------------------

SELECT last_name, first_name, employee_id
  FROM employees
 WHERE subsidiary_id = ?
   AND last_name LIKE ?

----------------------------------------------------------

SUBSIDIARY_ID 인덱스가 있고 LAST_NAME 인덱스가 있다고 가정하면 쿼리에 대해 어떤 것이 나은가요?

 

검색어에서 와일드카드의 위치를 모르면 적격한 답변을 제공할 없습니다.

optimizer "계속"하는 외에는 다른 선택의 여지가 없습니다. 항상 선행 와일드카드가 있다는 것을 알고 있는 경우, LIKE 조건을 의도적으로 난독화하여 optimizer 이상 LAST_NAME의의 인덱스를 고려할 없도록 있습니다.

----------------------------------------------------------

SELECT last_name, first_name, employee_id
  FROM employees
 WHERE subsidiary_id = ?
   AND
last_name || '' LIKE ?

----------------------------------------------------------

LAST_NAME 열에 문자열을 추가하기에 충분합니다.

그러나 이것은 최후의 수단입니다. 필요할때만 하세요.