SELECT

일반적으둜 INSERT / UPDATE / DELETE λŠ” 거의 λ ˆμ½”λ“œ λ‹¨μœ„λ‘œ λ°œμƒν•˜κΈ° 떄문에 μ„±λŠ₯상 λ¬Έμ œκ°€ μ—†λ‹€. ν•˜μ§€λ§Œ SELECTλŠ” μ—¬λŸ¬ 개의 ν…Œμ΄λΈ”λ‘œλΆ€ν„° 데이터λ₯Ό κ°€μ Έμ˜€κΈ° λ•Œλ¬Έμ— μ–΄λ–€ λ°©μ‹μœΌλ‘œ 데이터λ₯Ό κ°€μ Έμ˜¬μ§€μ— 따라 μ„±λŠ₯이 크게 달라진닀.

SELECT 절의 인덱슀 μ‚¬μš©

인덱슀 μ‚¬μš©μ„ μœ„ν•œ κΈ°λ³Έ κ·œμΉ™

기본적으둜 컬럼의 κ°’ 자체λ₯Ό λ³€ν™˜ν•˜μ§€ μ•Šκ³  κ·ΈλŒ€λ‘œ μ‚¬μš©ν•˜λŠ” 쑰건을 λ§Œμ‘±ν•΄μ•Ό 인덱슀λ₯Ό μ •μƒμ μœΌλ‘œ μ‚¬μš©ν•  수 μžˆλ‹€.

-- 인덱슀 μ‚¬μš© λΆˆκ°€
SELECT *
FROM salaries
WHERE salary * 10 > 1000000;

-- 인덱슀 μ‚¬μš© κ°€λŠ₯
SELECT *
FROM salaries
WHERE salary > 1000000 / 10;

λ˜ν•œ 비ꡐ λŒ€μƒμ΄ λ‹€λ₯Έ νƒ€μž…μ„ κ°€μ§€κ²Œ 되면 λ‚΄λΆ€μ μœΌλ‘œ ν˜• λ³€ν™˜μ΄ λ°œμƒν•˜κ²Œ λ˜λŠ”λ° 이 κ²½μš°μ—λ„ 인덱슀λ₯Ό μ‚¬μš©ν•  수 μ—†λ‹€.

WHERE 절의 인덱슀

WHERE μ‘°κ±΄μ—μ„œ μ—¬λŸ¬ 개의 μ»¬λŸΌμ„ μ‘°ν•©ν•˜μ—¬ μ‚¬μš©ν•˜λŠ” κ²½μš°μ—λŠ” 인덱슀λ₯Ό μ–΄λ–»κ²Œ κ΅¬μ„±ν•˜λŠλƒμ— 따라 μ„±λŠ₯이 크게 달라진닀. μ—¬κΈ°μ„œ μ‹€μ œλ‘œ μž‘μ„± 된 μˆœμ„œλ‘œ μΈλ±μŠ€κ°€ κ΅¬μ„±λ˜λŠ” 것이 μ•„λ‹ˆλΌ 인덱슀의 컬럼 μˆœμ„œμ— 따라 μ΅œμ ν™” μˆ˜ν–‰μ„ ν•˜κ²Œ 되기 λ•Œλ¬Έμ— 인덱슀의 컬럼 μˆœμ„œλ₯Ό 잘 κ³ λ €ν•΄μ•Ό ν•œλ‹€. μ—¬κΈ°μ„œ μœ„μ˜ μ„€λͺ…은 λͺ¨λ‘ AND 쑰건에 ν•΄λ‹Ήν•˜λŠ” 경우이며, OR 쑰건의 κ²½μš°μ—λŠ” 처리 방식이 λ°”λ€Œκ²Œ λœλ‹€.

SELECT *
FROM employees
WHERE first_name = 'Platypus' -- 인덱슀 μ‚¬μš© κ°€λŠ₯
   OR last_name = 'Ogu'; -- 인덱슀 μ‚¬μš© λΆˆκ°€λŠ₯

λ§Œμ•½ WHERE 쑰건에 OR 쑰건이 걸렀있고, μœ„μ™€ 같이 μΈλ±μŠ€κ°€ μ„€μ • λ˜μ–΄μžˆλŠ” 경우 AND의 경우 first_name 인덱슀λ₯Ό μ‚¬μš©ν•  수 μžˆμ§€λ§Œ, OR μ—°μ‚°μžκ°€ μ μš©λ˜μ–΄ 각 쑰건이 λ³„κ°œλ‘œ 처리되기 λ•Œλ¬Έμ— ν’€ ν…Œμ΄λΈ” μŠ€μΊ”μ΄ λ°œμƒν•˜κ²Œ λœλ‹€.

GROUP BY 절의 인덱슀

GROUP BY μ ˆμ—μ„œλŠ” 인덱슀λ₯Ό μ‚¬μš©ν•˜κΈ° μœ„ν•΄μ„  μ•„λž˜μ˜ 쑰건을 λ§Œμ‘±ν•΄μ•Ό ν•œλ‹€.

  • GROUP BY μ ˆμ— λͺ…μ‹œλœ 컬럼이 인덱슀 컬럼 μˆœμ„œμ™€ μœ„μΉ˜κ°€ 동일해야 ν•œλ‹€.

  • 인덱슀 ꡬ성 컬럼 쀑 λ’€μͺ½ μ»¬λŸΌμ€ GROUP BY μ ˆμ— λͺ…μ‹œλ˜μ§€ μ•Šμ•„λ„ 인덱슀λ₯Ό μ‚¬μš©ν•  수 μžˆμ§€λ§Œ, μ•žμͺ½ 컬럼이 GROUP BY μ ˆμ— λͺ…μ‹œλ˜μ§€ μ•ŠμœΌλ©΄ 인덱슀 μ‚¬μš©μ΄ λΆˆκ°€λŠ₯ν•˜λ‹€.

ORDER BY 절의 인덱슀

GROUP BY 처리 방법과 λΉ„μŠ·ν•˜λ©° 기본적으둜 μœ„μ˜ GROUP BY 절의 인덱슀λ₯Ό μ‚¬μš©ν•  수 μžˆλŠ” 쑰건을 λ”°λ₯΄κ²Œ 되며 μΆ”κ°€μ μœΌλ‘œ μ•„λž˜μ˜ 쑰건을 λ§Œμ‘±ν•΄μ•Ό ν•œλ‹€.

  • ORDER BY μ ˆμ— λͺ…μ‹œλœ λͺ¨λ“  컬럼이 μ˜€λ¦„μ°¨μˆœμ΄κ±°λ‚˜ λ‚΄λ¦Όμ°¨μˆœμœΌλ‘œ μ •λ ¬λ˜μ–΄μ•Ό ν•œλ‹€.

WHERE + ORDER BY(or GROUP BY) 절의 인덱슀

WHERE 절과 ORDER BY μ ˆμ„ λ™μ‹œμ— μ‚¬μš©ν•˜λŠ” κ²½μš°μ—λŠ” μ•„λž˜μ˜ λ°©λ²•μœΌλ‘œ 인덱슀λ₯Ό μ΄μš©ν•˜κ²Œ λœλ‹€.

  • WHERE 절만 인덱슀 이용

    • ORDER BY μ ˆμ€ 인덱슀λ₯Ό μ΄μš©ν•œ 정렬이 λΆˆκ°€λŠ₯ν•˜λ©°, WHERE 절의 λŒ€μƒ 컬럼이 μΈλ±μŠ€μ— 포함돼 μžˆμ„ λ•Œ μ‚¬μš© κ°€λŠ₯

    • WHERE 인덱슀λ₯Ό 톡해 쑰회된 κ²°κ³Όλ₯Ό λ³„λ„λ‘œ μ •λ ¬ν•˜λŠ” λ°©μ‹μœΌλ‘œ μ²˜λ¦¬λœλ‹€.

    • WHERE 절 쑰건에 μΌμΉ˜ν•˜λŠ” λ ˆμ½”λ“œ κ±΄μˆ˜κ°€ 적을 수둝 μ„±λŠ₯이 μ’‹λ‹€.

  • ORDER BY 절만 인덱슀 이용

    • WHERE μ ˆμ€ 인덱슀λ₯Ό μ΄μš©ν•œ μ‘°νšŒκ°€ λΆˆκ°€λŠ₯ν•˜λ©°, ORDER BY 절의 μ •λ ¬ λŒ€μƒ 컬럼이 μΈλ±μŠ€μ— 포함돼 μžˆμ„ λ•Œ μ‚¬μš© κ°€λŠ₯

    • ORDER BY 절의 μˆœμ„œλŒ€λ‘œ 인덱슀λ₯Ό μ½μœΌλ©΄μ„œ λ ˆμ½”λ“œ ν•œ 건씩 WHERE 쑰건에 μΌμΉ˜ν•˜λŠ”μ§€ ν™•μΈν•˜λŠ” λ°©μ‹μœΌλ‘œ μ²˜λ¦¬λœλ‹€.

  • WHERE 절 + ORDER BY 절 λ™μ‹œμ— 같은 인덱슀 이용

    • WHERE 절의 λ²”μœ„ 비ꡐ μ‘°κ±΄μ—μ„œ μ‚¬μš©ν•˜λŠ” 컬럼과 ORDER BY 절의 μ •λ ¬ λŒ€μƒ 컬럼이 λͺ¨λ‘ ν•˜λ‚˜μ˜ μΈλ±μŠ€μ— μ—°μ†ν•΄μ„œ 포함돼 μžˆμ„ λ•Œ μ‚¬μš© κ°€λŠ₯

    • WHERE 절의 동등 비ꡐ 쑰건으둜 μ‚¬μš©ν•˜λŠ” 컬럼과 ORDER BY μ ˆμ— μ •λ ¬ λŒ€μƒ 컬럼이 쀑첩 상관 없이 인덱슀 μˆœμ„œλŒ€λ‘œ 포함돼 μžˆμ„ λ•Œ μ‚¬μš© κ°€λŠ₯

    • 제일 λΉ λ₯Έ μ„±λŠ₯을 보이기 λ•Œλ¬Έμ— κ°€λŠ₯ν•˜λ‹€λ©΄ 이 방법을 μ‚¬μš©ν•˜λŠ” 것이 μ’‹λ‹€.

-- 1
SELECT *
FROM tb_test
WHERE COL_1 = 10
ORDER BY COL_2, COL_3;

-- 2
SELECT *
FROM tb_test
WHERE COL_1 = 10
ORDER BY COL_1, COL_2, COL_3;

μœ„ μΏΌλ¦¬λŠ” 동등 비ꡐ이기 λ•Œλ¬Έμ— 1λ²ˆμ—μ„œ COL_1 GROUP BY μ ˆμ— μΆ”κ°€ν•˜λ”λΌλ„ μ •λ ¬ μˆœμ„œμ— λ³€ν™”κ°€ μ—†μ–΄(COL_1에 λŒ€ν•œ 데이터가 ν•œ 건이기 λ•Œλ¬Έ) μ‹€ν–‰ κ²°κ³Όκ°€ κ°™λ‹€. λ•Œλ¬Έμ— μ˜΅ν‹°λ§ˆμ΄μ €μ—μ„œ μ‹€ν–‰ κ³„νšμ„ μ΅œμ ν™”ν•˜μ—¬ WHERE + GROUP BY 절 인덱슀 μ‚¬μš© λ°©μ‹μœΌλ‘œ μ²˜λ¦¬ν•  수 있게 λœλ‹€.

-- 1
SELECT *
FROM tb_test
WHERE COL_1 > 10
ORDER BY COL_2, COL_3;

-- 2
SELECT *
FROM tb_test
WHERE COL_1 > 10
ORDER BY COL_1, COL_2, COL_3;

ν•˜μ§€λ§Œ μœ„ μΏΌλ¦¬λŠ” λ²”μœ„ 비ꡐ이기 λ•Œλ¬Έμ— COL_1 > 10 을 λ§Œμ‘±ν•˜λŠ” λ ˆμ½”λ“œκ°€ μ—¬λŸ¬ 개 일 수 있기 λ•Œλ¬Έμ—, 1λ²ˆμ€ 정렬을 ν•  λ•Œ 인덱슀λ₯Ό μ‚¬μš©ν•  수 μ—†κ²Œ 되고, 2λ²ˆμ€ κ·ΈλŒ€λ‘œ λͺ¨λ‘ 인덱슀λ₯Ό μ‚¬μš©ν•  수 있게 λœλ‹€.

GROUP BY + ORDER BY 절의 인덱슀

GROUP BY 절과 ORDER BY μ ˆμ— λͺ…μ‹œλœ 컬럼의 μˆœμ„œμ™€ λ‚΄μš©μ΄ λͺ¨λ‘ κ°™μ•„μ•Ό 인덱슀λ₯Ό μ‚¬μš©ν•  수 μžˆλ‹€. λ§Œμ•½ λ‘˜ 쀑 ν•˜λ‚˜λΌλ„ 인덱슀λ₯Ό μ΄μš©ν•  수 없을 경우 λͺ¨λ‘ 인덱슀λ₯Ό μ‚¬μš©ν•  수 μ—†λ‹€.

WHERE + GROUP BY + ORDER BY 절의 인덱슀

μœ„μ˜ κ·œμΉ™μ΄ λͺ¨λ‘ 적용되며, κ·Έ 흐름은 μ•„λž˜μ™€ κ°™λ‹€.

WHERE 절 비ꡐ 쑰건 μ‚¬μš© μ‹œ μ£Όμ˜μ‚¬ν•­

NULL 비ꡐ

MySQLμ—μ„œλŠ” NULL 값도 ν•˜λ‚˜μ˜ κ°’μœΌλ‘œ μΈμ •ν•˜μ—¬ ν¬ν•¨λœ λ ˆμ½”λ“œλ„ 인덱슀둜 κ΄€λ¦¬ν•œλ‹€.(SQL ν‘œμ€€μ—μ„œλŠ” NULL 값은 비ꡐ할 수 μ—†λŠ” κ°’μœΌλ‘œ μ •μ˜λ˜μ–΄ 있음) ν•˜μ§€λ§Œ λͺ¨λ“  쿼리 μ‹€ν–‰ κ³„νšμ—μ„œ NULL 값을 λ ˆμΈμ§€ μŠ€μΊ”μœΌλ‘œ μ²˜λ¦¬ν•˜μ§€λŠ” μ•ŠλŠ”λ‹€.

-- 1
SELECT *
FROM titles
WHERE to_date IS NULL;
-- 2
SELECT *
FROM titles
WHERE ISNULL(to_date);
-- 3
SELECT *
FROM titles
WHERE ISNULL(to_date) = 1;
-- 4
SELECT *
FROM titles
WHERE ISNULL(to_date) = true; # 4

1 / 2 μΏΌλ¦¬λŠ” μ •μƒμ μœΌλ‘œ λ ˆμΈμ§€ μŠ€μΊ”μ„ μ‚¬μš©ν•˜μ§€λ§Œ, 3 / 4 μΏΌλ¦¬λŠ” λ ˆμΈμ§€ μŠ€μΊ”μ„ μ‚¬μš©ν•˜μ§€ λͺ»ν•˜κ³  ν’€ μŠ€μΊ”μ„ μ‚¬μš©ν•˜κ²Œ λœλ‹€.

λ¬Έμžμ—΄ / 숫자 비ꡐ

λ¬Έμžμ—΄ / 숫자 컬럼 비ꡐ μ‹œ λ°˜λ“œμ‹œ κ·Έ νƒ€μž…μ— λ§žλŠ” μƒμˆ˜κ°’ μ‚¬μš©ν•΄μ•Ό 인덱슀λ₯Ό μ •μƒμ μœΌλ‘œ μ‚¬μš©ν•  수 μžˆλ‹€.

λ‚ μ§œ 비ꡐ

λ‚ μ§œλ₯Ό μ €μž₯ν•˜λŠ” νƒ€μž…μ—λŠ” DATETIME, DATE, TIMESTAMP, TIME 이 μ‘΄μž¬ν•˜κΈ° λ•Œλ¬Έμ— 각각 νƒ€μž…μ„ 비ꡐ할 λ•Œ μ£Όμ˜ν•΄μ•Ό ν•œλ‹€.

DATE(DATETIME) - λ¬Έμžμ—΄ 비ꡐ

기본적으러 λ¬Έμžμ—΄ 값을 STR_TO_DATEλ₯Ό λͺ…μ‹œν•˜μ§€ μ•Šμ•„λ„ μžλ™μœΌλ‘œ DATETIME νƒ€μž…μœΌλ‘œ λ³€ν™˜ν•˜μ—¬ 비ꡐλ₯Ό μˆ˜ν–‰ν•˜κ²Œ λœλ‹€.(인덱슀 λ˜ν•œ 정상 적용) μ΄λ ‡κ²Œ μƒμˆ˜λ₯Ό λ³€ν™˜ν•˜λŠ” 것은 인덱슀λ₯Ό μ‚¬μš©ν•˜λŠ”λ°μ— 영ν–₯이 μ—†μ§€λ§Œ, λ‚ μ§œ μ»¬λŸΌμ„ DATE_FORMAT, DATE_ADD λ“±μ˜ ν•¨μˆ˜λ₯Ό μ‚¬μš©ν•˜μ—¬ λ³€ν™˜ν•˜λŠ” κ²½μš°μ—λŠ” 인덱슀λ₯Ό μ‚¬μš©ν•  수 μ—†λ‹€.

DATE - DATETIME 비ꡐ

λ³€ν™˜μ„ λ”°λ‘œ λͺ…μ‹œν•˜μ§€ μ•ŠλŠ” κ²½μš°μ—” DATE μ»¬λŸΌμ„ DATETIME νƒ€μž…μœΌλ‘œ λ³€ν™˜ν•˜μ—¬ 비ꡐλ₯Ό μˆ˜ν–‰ν•˜κ²Œ λœλ‹€. 2023-05-09 -> 2023-05-09 00:00:00 으둜 λ³€ν™˜λ˜λŠ”λ°, ν•΄λ‹Ή νƒ€μž… λ³€ν™˜μ€ 인덱슀 μ‚¬μš© 여뢀에 영ν–₯을 주지 μ•Šμ•„ 쿼리 κ²°κ³Όμ—λ§Œ 주의λ₯Ό ν•˜λ©΄ λœλ‹€.

TIMESTAMP - DATETIME 비ꡐ

DATETIME - TIMESTAMP 별도 νƒ€μž… λ³€ν™˜ 없이 비ꡐ μ‹œ λ¬Έμ œμ—†μ΄ μž‘λ™ν•˜λŠ” κ²ƒμ²˜λŸΌ 보일 수 μžˆμ§€λ§Œ μ‹€μ œλ‘œλŠ” 그렇지 μ•Šμ„ 수 있기 λ•Œλ¬Έμ— μ£Όμ˜ν•΄μ•Ό ν•œλ‹€.

SELECT COUNT(*)
FROM employees
WHERE hire_date < UNIX_TIMESTAMP('2023-05-09 12:05:09'); -- hire_date: datetime νƒ€μž…

UNIX_TIMESTAMP ν•¨μˆ˜λŠ” λ‚΄λΆ€μ μœΌλ‘œ λ‹¨μˆœ 숫자 값에 λΆˆκ³Όν•˜κΈ° λ•Œλ¬Έμ— μ •μƒμ μœΌλ‘œ DATETIME νƒ€μž…μœΌλ‘œ λ³€ν™˜λ˜μ§€ μ•Šμ•„ μ˜¬λ°”λ₯΄μ§€ μ•Šμ€ κ²°κ³Όλ₯Ό λ°˜ν™˜ν•˜κ²Œ λœλ‹€. 이런 κ²½μš°μ—λŠ” FROM_UNIXTIME ν•¨μˆ˜λ₯Ό μ‚¬μš©ν•˜μ—¬ νƒ€μž… λ³€ν™˜μ„ λͺ…μ‹œν•΄μ•Ό ν•œλ‹€.

SELECT COUNT(*)
FROM employees
WHERE hire_date < FROM_UNIXTIME(UNIX_TIMESTAMP('2023-05-09 12:05:09')); -- hire_date: datetime νƒ€μž…

Short Circuit Evaluation

기본적으둜 WHERE 쑰건 쀑 μΈλ±μŠ€κ°€ μžˆλŠ” κ²½μš°μ—” ν•΄λ‹Ή μ»¬λŸΌμ„ λ¨Όμ € 쑰건 κ²€μ‚¬ν•˜μ§€λ§Œ, μ•„λ‹Œ κ²½μš°μ—” WHERE에 λͺ…μ‹œλœ μˆœμ„œλŒ€λ‘œ 쑰건 검사λ₯Ό μˆ˜ν–‰ν•œλ‹€. 떄문에 λ§Žμ€ λ¦¬μ†ŒμŠ€κ°€ μ†Œλͺ¨ν•˜λŠ” 쑰건을 λ‚˜μ€‘μ— λͺ…μ‹œν•˜λ©΄ 더 λΉ λ₯΄κ²Œ 쿼리λ₯Ό μˆ˜ν–‰ν•  수 μžˆλ‹€.

LIMIT n

쿼리 κ²°κ³Όμ—μ„œ μ§€μ •λœ μˆœμ„œμ— μœ„μΉ˜ν•œ λ ˆμ½”λ“œλ§Œ κ°€μ Έμ˜¬ λ•Œ μ‚¬μš©ν•˜λŠ” 문법이닀. MySQL의 LIMIT은 WHERE 쑰건이 μ•„λ‹ˆκΈ° λ•Œλ¬Έμ— 항상 쿼리의 λ§ˆμ§€λ§‰μ— μ‹€ν–‰λœλ‹€.

SELECT *
FROM employees
WHERE emp_no BETWEEN 10001 AND 10010 -- 1. employees ν…Œμ΄λΈ”μ—μ„œ WHERE 쑰건에 μΌμΉ˜ν•˜λŠ” λ ˆμ½”λ“œλ₯Ό μ „λΆ€ 읽음
ORDER BY first_name -- 2. 1λ²ˆμ—μ„œ μ½μ–΄μ˜¨ λ ˆμ½”λ“œλ₯Ό first_name μ»¬λŸΌκ°’μ— 따라 μ •λ ¬
LIMIT 0, 5; -- 3. μ •λ ¬λœ κ²°κ³Όμ—μ„œ 상쉬 5개의 λ ˆμ½”λ“œλ§Œ λ°˜ν™˜

LIMIT은 ν•„μš”ν•œ λ ˆμ½”λ“œ κ±΄μˆ˜κ°€ 쑰회되면 μ¦‰μ‹œ 쿼리λ₯Ό μ’…λ£Œν•˜κ²Œ λ˜λŠ”λ°, 쿼리에 따라 μ„±λŠ₯ ν–₯상을 κΈ°λŒ€ν•  수 μžˆλ‹€.

  • 인덱슀 처리 λ˜μ§€ μ•Šμ€ GROUP BY / ORDER BY: λͺ¨λ“  λ ˆμ½”λ“œλ₯Ό 읽어야 ν•˜λ―€λ‘œ μ„±λŠ₯ ν–₯상 λ―Έλ―Έ

  • DISTINCT: μœ λ‹ˆν¬ν•œ λ ˆμ½”λ“œ κ±΄μˆ˜κ°€ LIMIT에 λͺ…μ‹œλœ 값보닀 큰 경우 μ„±λŠ₯ ν–₯상 κΈ°λŒ€(ν…Œμ΄λΈ”μ„ μ½λŠ” 도쀑 쀑단)

  • μœ„μ— ν•΄λ‹Ήν•˜μ§€ μ•ŠμŒ: 큰 μ„±λŠ₯ ν–₯상 κΈ°λŒ€ κ°€λŠ₯

νŽ˜μ΄μ§•

μ§κ΄€μ μœΌλ‘œ νŽ˜μ΄μ§•ν•˜λŠ” 방법은 LIMIT을 톡해 νŽ˜μ΄μ§€ λ²ˆν˜Έμ™€ νŽ˜μ΄μ§€ λ‹Ή λ ˆμ½”λ“œ 수λ₯Ό κ³±ν•œ 값을 LIMIT에 λͺ…μ‹œν•˜λŠ” 것이닀.

  • 일반적인 LIMIT μ‚¬μš©

SELECT *
FROM salaries
ORDER BY salary
LIMIT 200000, 10;

적은 μ–‘μ˜ λ°μ΄ν„°μ—μ„œλŠ” λ¬Έμ œκ°€ λ˜μ§€ μ•Šμ§€λ§Œ μ„±λŠ₯에 영ν–₯을 쀄 μ •λ„μ˜ μ–‘μ˜ 데이터λ₯Ό μ‘°νšŒν•˜λŠ” 경우 ν•΄λ‹Ή νŽ˜μ΄μ§€κΉŒμ§€μ˜ λͺ¨λ“  λ ˆμ½”λ“œλ₯Ό 읽어야 ν•˜κΈ° λ•Œλ¬Έμ— μ„±λŠ₯에 영ν–₯을 쀄 수 μžˆλ‹€.

  • 포인터(μ»€μ„œ) κ°œλ…μ„ μ‚¬μš©ν•œ νŽ˜μ΄μ§•

-- 첫 νŽ˜μ΄μ§€ 쑰회
SELECT *
FROM salaries
ORDER BY salary
LIMIT 0, 10;

-- κ·Έ λ‹€μŒ νŽ˜μ΄μ§€ 쑰회
SELECT *
FROM salaries
WHERE salary >= 5959
  AND NOT (salary = 5959 AND emp_no <= 10001) -- 첫 νŽ˜μ΄μ§€μ—μ„œ κ°€μž₯ λ§ˆμ§€λ§‰ λ ˆμ½”λ“œμ˜ salary κ°’
ORDER BY salary
LIMIT 0, 10;

-- ...
-- κ³„μ†ν•΄μ„œ λ‹€μŒ νŽ˜μ΄μ§€ 쑰회
SELECT *
FROM salaries
WHERE salary >= 1295000
  AND NOT (salary = 1295000 AND emp_no <= 20344) -- 이전 νŽ˜μ΄μ§€μ—μ„œ κ°€μž₯ λ§ˆμ§€λ§‰ λ ˆμ½”λ“œμ˜ salary κ°’
ORDER BY salary
LIMIT 0, 10;

μœ„μ™€ 같이 포인터(μ»€μ„œ) κ°œλ…μ„ μ‚¬μš©ν•˜λ©΄ 데이터 κ±΄μˆ˜μ— 따라 비약적인 μ„±λŠ₯ ν–₯상을 κΈ°λŒ€ν•  수 μžˆλ‹€.

COUNT()

κ²°κ³Ό λ ˆμ½”λ“œμ˜ 건수λ₯Ό λ°˜ν™˜ν•˜λŠ” ν•¨μˆ˜

  • λ‚΄λΆ€ 인자

    • 컬럼λͺ… / * / 1 μ‚¬μš© κ°€λŠ₯

    • *λŠ” SELECT μ ˆμ—μ„œ μ‚¬μš©λ˜λŠ” κ²ƒμ²˜λŸΌ λͺ¨λ“  μ»¬λŸΌμ„ κ°€μ Έμ˜€λŠ” 것을 μ˜λ―Έν•˜λŠ” 것이 μ•„λ‹Œ, μ˜΅ν‹°λ§ˆμ΄μ €κ°€ μ΅œμ ν™”ν•˜μ—¬ κ°€μž₯ λΉ λ₯΄κ²Œ μ²˜λ¦¬ν•  수 μžˆλŠ” 컬럼 μ‚¬μš©

      • μ‚¬μš© κ°€λŠ₯ν•œ κ°€μž₯ μž‘μ€ 세컨더리 인덱슀λ₯Ό νƒμƒ‰ν•˜μ—¬ 처리(μ—†λŠ” 경우, ν΄λŸ¬μŠ€ν„°λœ PK 인덱슀 μ‚¬μš©)

    • λ§Œμ•½ 인자둜 μ»¬λŸΌμ„ 넣은 경우 ν•΄λ‹Ή 컬럼이 NULL이 μ•„λ‹Œ λ ˆμ½”λ“œλ§Œ 카운트

  • WHERE 쑰건

    • WHERE 쑰건이 μ—†λŠ” 경우 ν΄λŸ¬μŠ€ν„° 인덱슀λ₯Ό 순차적으둜 μŠ€μΊ”ν•˜μ—¬ λ ˆμ½”λ“œ 건수λ₯Ό 카운트(MyISAM 엔진: 메타 데이터λ₯Ό μ‚¬μš©)

      • 쑰건절 / GROUP BY λ‘˜ λ‹€ μ—†λŠ” 경우 쿼리 μ΅œμ ν™”λ₯Ό 톡해 λ ˆμ½”λ“œ 건수λ₯Ό μ΅œμ ν™”ν•˜μ—¬ λΉ λ₯΄κ²Œ κ°€μ Έμ˜¬ 수 있음

      • **InnoDBμ—μ„œ 메타 데이터λ₯Ό μ‚¬μš©ν•˜μ§€ μ•ŠλŠ” 이유: MVCC 지원과 데이터 무결성을 μœ„ν•΄ νŠΈλžœμž­μ…˜ λ‹¨μœ„λ‘œ 데이터λ₯Ό κ΄€λ¦¬ν•˜κΈ° λ•Œλ¬Έ

    • 쑰건이 μžˆλŠ” κ²½μš°μ—” WHERE 쑰건에 μΌμΉ˜ν•˜λŠ” λ ˆμ½”λ“œ μ‘°νšŒν•˜κΈ° λ•Œλ¬Έμ— 일반적인 DBMS와 λ™μΌν•˜κ²Œ 처리

  • ORDER BY

    • 개수 쑰회λ₯Ό ν•˜λŠ” 데에 정렬이 ν•„μš”ν•˜μ§€ μ•ŠκΈ° λ•Œλ¬Έμ— λΆˆν•„μš”ν•œ μ„±λŠ₯ μ €ν•˜λ₯Ό μœ λ°œν•  수 있음(MySQL 8.0 미만)

    • MySQL 8.0 μ΄μƒλΆ€ν„°λŠ” ORDER BYλ₯Ό μ‚¬μš©ν•˜λ”λΌλ„ μ˜΅ν‹°λ§ˆμ΄μ €μ—μ„œ μ΅œμ ν™”(λ¬΄μ‹œ)ν•˜μ—¬ μ„±λŠ₯ μ €ν•˜λ₯Ό 방지

JOIN()

쑰인 μž‘μ—…μ—μ„œ λ“œλΌμ΄λΉ™ ν…Œμ΄λΈ”μ„ 읽을 λ•ŒλŠ” 인덱슀 탐색 μž‘μ—…μ„ ν•œ 번만 μˆ˜ν–‰ν•˜κ³ , λ“œλ¦¬λΈ ν…Œμ΄λΈ”μ„ 읽을 λ•ŒλŠ” 인덱슀 탐색 μž‘μ—…μ„ λ ˆμ½”λ“œ 건수만큼 μˆ˜ν–‰ν•˜κ²Œ λœλ‹€. λ•Œλ¬Έμ— JOIN μˆœμ„œμ™€ 인덱슀 μœ λ¬΄μ— 따라 μ„±λŠ₯에 크게 영ν–₯을 주게 λ˜λŠ”λ°, 이λ₯Ό μ˜΅ν‹°λ§ˆμ΄μ €κ°€ μ΅œμ ν™”ν•˜μ—¬ μ„±λŠ₯ μ €ν•˜λ₯Ό λ°©μ§€ν•˜λŠ” μͺ½μœΌλ‘œ λ™μž‘ν•œλ‹€.

SELECT *
FROM employees e,
     dept_emp de
WHERE e.emp_no = de.emp_no;

μœ„μ˜ 쿼리가 μ‘΄μž¬ν•  λ•Œ μ˜΅ν‹°λ§ˆμ΄μ €λŠ” μ•„λž˜μ™€ 같이 λ™μž‘ν•œλ‹€.(무쑰건 μ•„λž˜μ™€ 같이 λ™μž‘ν•˜λŠ” 것은 μ•„λ‹ˆμ§€λ§Œ λŒ€λΆ€λΆ„μ˜ 경우 μ•„λž˜μ™€ 같이 λ™μž‘ν•œλ‹€.)

emp_no 인덱슀
dept_no 인덱슀
쑰인 μˆœμ„œμ™€ μ˜΅ν‹°λ§ˆμ΄μ € λ™μž‘

O

O

μ–΄λŠ ν…Œμ΄λΈ”μ„ λ“œλΌμ΄λΉ™μœΌλ‘œ μ„ νƒν•˜λ“  인덱슀λ₯Ό μ΄μš©ν•΄ λ“œλ¦¬λΈ ν…Œμ΄λΈ” 쑰회λ₯Ό λΉ λ₯΄κ²Œ μ²˜λ¦¬ν•˜κΈ° λ•Œλ¬Έμ— 톡계 정보λ₯Ό μ΄μš©ν•΄ 적절히 선택

O

X

dept_emp ν…Œμ΄λΈ”μ„ λ“œλΌμ΄λΉ™ ν…Œμ΄λΈ”λ‘œ μ„ νƒν•˜μ—¬ ν…Œμ΄λΈ” ν’€ μŠ€μΊ”μ„ ν•œ 번만 μˆ˜ν–‰ν•  수 μžˆλ„λ‘ ν•˜κ³ , employees ν…Œμ΄λΈ”μ„ λ“œλ¦¬λΈ ν…Œμ΄λΈ”λ‘œ μ„ νƒν•˜μ—¬ 인덱슀λ₯Ό μ΄μš©ν•΄ μ‘°νšŒν•  수 μžˆλ„λ‘ 함

X

O

μœ„μ™€ λ°˜λŒ€λ‘œ λ™μž‘

X

X

μ–΄λ–€ κ²½μš°μ—μ„œλ“  λ“œλ¦¬λΈ ν…Œμ΄λΈ”μ˜ ν’€ μŠ€μΊ”μ΄ λ°œμƒν•˜κΈ° λ•Œλ¬Έμ— λ ˆμ½”λ“œ κ±΄μˆ˜κ°€ 적은 ν…Œμ΄λΈ”μ„ λ“œλΌμ΄λΉ™ ν…Œμ΄λΈ”λ‘œ μ„ νƒν•˜κ²Œ λœλ‹€.

λ˜ν•œ WHERE 쑰건과 λ§ˆμ°¬κ°€μ§€λ‘œ JOIN μ‘°κ±΄μ—μ„œμ˜ 비ꡐ λŒ€μƒ 컬럼이 μ„œλ‘œ 동일해야 인덱슀λ₯Ό 효율적으둜 μ‚¬μš©ν•  수 μžˆλ‹€.(μ•„λ‹Œ 경우 ν…Œμ΄λΈ” ν’€ μŠ€μΊ”μ΄ λ°œμƒν•  수 μžˆλ‹€.)

지연 쑰인(Delayed Join)

쑰인을 μ‚¬μš©ν•˜μ—¬ GROUP BY, ORDER BY λ“±μ˜ μž‘μ—…μ„ μˆ˜ν–‰ν•  λ•Œ, 인덱슀λ₯Ό μ‚¬μš©ν•˜κ³  μžˆλ‹€λ©΄ μ˜΅ν‹°λ§ˆμ΄μ €κ°€ 졜적으둜 μ²˜λ¦¬ν•˜κ³  μžˆμ„ ν™•λ₯ μ΄ λ†’λ‹€. ν•˜μ§€λ§Œ 그렇지 μ•Šμ€ κ²½μš°μ—” λ¨Όμ € 쑰인을 μˆ˜ν–‰ν•˜κ³  GROUP BY, ORDER BY λ“±μ˜ μž‘μ—…μ„ μˆ˜ν–‰ν•˜κ²Œ λ˜μ–΄ μ•„λž˜μ˜ λ¬Έμ œκ°€ λ°œμƒν•  수 μžˆλ‹€.

  • 쑰인을 ν•  수둝 λ ˆμ½”λ“œ κ±΄μˆ˜μ™€ λ ˆμ½”λ“œ 자체의 크기가 λŠ˜μ–΄λ‚¨

  • GROUP BY, ORDER BY λ“±μ˜ μž‘μ—…μ„ μˆ˜ν–‰ν•  λ•Œ λ ˆμ½”λ“œ κ±΄μˆ˜κ°€ λ§Žκ±°λ‚˜ λ ˆμ½”λ“œ 자체의 크기가 크닀면 μ„±λŠ₯ μ €ν•˜ λ°œμƒ

λ•Œλ¬Έμ—, λ¨Όμ € GROUP BY, ORDER BY λ“±μ˜ μž‘μ—…μ„ μˆ˜ν–‰ν•˜κ³  쑰인을 μˆ˜ν–‰ν•˜λŠ” 것이 μ’‹λ‹€.

  • 지연 쑰인 적용 μ „

SELECT e.*
FROM salaries s,
     employees e
WHERE e.emp_no = s.emp_no
  AND s.emp_no BETWEEN 10001 AND 13000
GROUP BY s.emp_no
ORDER BY SUM(s.salary) DESC
LIMIT 10;
  1. employees ν…Œμ΄λΈ”μ„ λ“œλΌμ΄λΉ™ ν…Œμ΄λΈ”λ‘œ 선택

  2. 10001 ~ 13000 μ‚¬μ΄μ˜ λ ˆμ½”λ“œλ₯Ό 쑰회

  3. salaries ν…Œμ΄λΈ”κ³Ό 쑰인(쑰인 ν›„ λ ˆμ½”λ“œ κ±΄μˆ˜κ°€ 증가)

  4. μœ„ κ²°κ³Όλ₯Ό μž„μ‹œν…Œμ΄λΈ”μ— μ €μž₯

  5. GROUP BY μž‘μ—… μˆ˜ν–‰ν•˜μ—¬ μ΅œλŒ€ 3000개의 λ ˆμ½”λ“œλ‘œ 쀄어듦

  6. ORDER BY μž‘μ—… μˆ˜ν–‰

  7. LIMIT 10으둜 μ΅œμ’… κ²°κ³Ό λ°˜ν™˜

  • 지연 쑰인 적용 ν›„

SELECT e.*
FROM (SELECT s.emp_no
      FROM salaries s
      WHERE s.emp_no BETWEEN 10001 AND 13000
      GROUP BY s.emp_no
      ORDER BY SUM(s.salary) DESC
      LIMIT 10) x,
     employees e
WHERE e.emp_no = x.emp_no;
  1. salaries ν…Œμ΄λΈ”μ—μ„œ 10001 ~ 13000 μ‚¬μ΄μ˜ λ ˆμ½”λ“œλ₯Ό 쑰회

  2. GROUP BY / ORDER BY / LIMIT μž‘μ—…μ„ μˆ˜ν–‰ν•˜μ—¬ μ΅œλŒ€ 10개의 λ ˆμ½”λ“œλ‘œ 쀄어듦

  3. employees ν…Œμ΄λΈ”κ³Ό 쑰인

μœ„μ˜ μ˜ˆμ‹œλŠ” 지연 쑰인을 μ μš©ν–ˆμ„ λ•Œ μ„±λŠ₯이 ν–₯μƒλ˜λŠ” μ˜ˆμ‹œμ΄μ§€λ§Œ, 지연 쑰인을 μ μš©ν–ˆμ„ λ•Œ μ„±λŠ₯이 μ €ν•˜λ˜λŠ” κ²½μš°λ„ μ‘΄μž¬ν•œλ‹€. 지연 쑰인을 μ μš©ν•˜μ—¬ μ„±λŠ₯ ν–₯상을 κΈ°λŒ€ν•˜λ €λ©΄ μ•„λž˜μ˜ 쑰건을 λ§Œμ‘±ν•΄μ•Ό ν•œλ‹€.

  • LEFT(OUTER) JOIN인 경우

    • λ“œλΌμ΄λΉ™ ν…Œμ΄λΈ”κ³Ό λ“œλ¦¬λΈ ν…Œμ΄λΈ”μ€ 1:1 λ˜λŠ” M:1 관계여야 ν•œλ‹€.

  • INNER JOIN인 경우

    • λ“œλΌμ΄λΉ™ ν…Œμ΄λΈ”κ³Ό λ“œλ¦¬λΈ ν…Œμ΄λΈ”μ΄ 1:1 λ˜λŠ” M:1 관계여야 ν•œλ‹€.

    • λ“œλΌμ΄λΉ™ ν…Œμ΄λΈ”μ— μžˆλŠ” λ ˆμ½”λ“œλŠ” λ“œλ¦¬λΈ ν…Œμ΄λΈ”μ— λͺ¨λ‘ μ‘΄μž¬ν•΄μ•Ό ν•œλ‹€.

λž˜ν„°λŸ΄ 쑰인(Lateral Join)

MySQL 8.0λΆ€ν„° μ§€μ›ν•˜λŠ” κΈ°λŠ₯으둜 νŠΉμ • κ·Έλ£Ήλ³„λ‘œ μ„œλΈŒμΏΌλ¦¬λ₯Ό μ‹€ν–‰ν•΄μ„œ κ²°κ³Όλ₯Ό λ°˜ν™˜ν•˜λŠ” κΈ°λŠ₯이닀.

-- employees ν…Œμ΄λΈ”μ—μ„œ first_name이 Matt인 λ ˆμ½”λ“œλ₯Ό μ‘°νšŒν•˜κ³ , 
-- salaries ν…Œμ΄λΈ”μ—μ„œ κ°€μž₯ μ΅œκ·Όμ— 받은 κΈ‰μ—¬ 2건을 μ‘°νšŒν•˜λŠ” 쿼리
SELECT *
FROM employees e
         LEFT JOIN LATERAL ( SELECT *
                             FROM salaries s
                             WHERE s.emp_no = e.emp_no
                             ORDER BY s.from_date DESC
                             LIMIT 2) s2 ON s2.emp_no = e.emp_no
WHERE e.first_name = 'Matt';

μ—¬κΈ°μ„œ νŠΉμ§•μ€ LATERAL ν‚€μ›Œλ“œλ₯Ό μ‚¬μš©ν•˜μ—¬ μ„œλΈŒμΏΌλ¦¬λ₯Ό μ‚¬μš©ν•˜κ³  μžˆλŠ”λ°, κ·Έ λ‚΄λΆ€μ—μ„œ μ™ΈλΆ€ 쿼리의 FROM μ ˆμ— μ •μ˜λœ ν…Œμ΄λΈ”μ˜ μ»¬λŸΌμ„ μ°Έμ‘°ν•  수 μžˆλ‹€λŠ” 것이닀. LATERAL ν‚€μ›Œλ“œλ₯Ό 가진 μ„œλΈŒμΏΌλ¦¬λŠ” 쑰인 μˆœμ„œμƒ ν›„μˆœμœ„λ‘œ 밀리고, μ™ΈλΆ€ 쿼리의 κ²°κ³Ό λ ˆμ½”λ“œ λ‹¨μœ„λ‘œ μž„μ‹œ ν…Œμ΄λΈ”μ΄ μƒμ„±λ˜μ–΄ μ²˜λ¦¬λœλ‹€.

ORDER BY

ORDER BYλŠ” λ ˆμ½”λ“œλ₯Ό μ–΄λ–€ μˆœμ„œλ‘œ μ •λ ¬ν•˜μ§€ κ²°μ •ν•˜λŠ” 절인데, λͺ…μ‹œν•˜μ§€ μ•ŠμœΌλ©΄ μ•„λž˜μ™€ 같이 μ •λ ¬λ˜μ–΄ λ°˜ν™˜λœλ‹€.

  • 인덱슀λ₯Ό μ‚¬μš©ν•˜μ—¬ 쑰회 된 κ²½μš°μ—” 인덱슀의 μ •λ ¬ μˆœμ„œλŒ€λ‘œ λ°˜ν™˜

  • InnoDBμ—μ„œ ν’€ ν…Œμ΄λΈ” μŠ€μΊ”μ„ ν•œ 경우 기본적으둜 프라이머리 ν‚€ μˆœμ„œλŒ€λ‘œ λ°˜ν™˜

  • SELECT 쿼리가 μž„μ‹œ ν…Œμ΄λΈ”μ„ μ‚¬μš©ν•˜μ—¬ μ‘°νšŒλμ„ κ²½μš°μ—” λ ˆμ½”λ“œ μˆœμ„œλ₯Ό μ˜ˆμΈ‘ν•˜κΈ° 어렀움

ORDER BY 2와 같이 컬럼의 μˆœλ²ˆμ„ μ§€μ •ν•˜μ—¬ μ •λ ¬ν•  μˆ˜λ„ μžˆμ§€λ§Œ, μ΄λŠ” 가독성이 떨어지고 μœ μ§€λ³΄μˆ˜κ°€ μ–΄λ €μ›Œμ§€κΈ° λ•Œλ¬Έμ— μ‚¬μš©ν•˜μ§€ μ•ŠλŠ” 것이 μ’‹λ‹€.

참고자료

Last updated

Was this helpful?