๋งค์ผ๋ฉ์ผ ๋ฐฑ์๋ ์ง๋ฌธ์ ์ฐธ๊ณ ํด ๊ฐ์ธ์ ์ผ๋ก ํ์ตํ ๋ด์ฉ์ ์ ๋ฆฌํ์์ต๋๋ค.
์ค๋ฅ๊ฐ ์๋ค๋ฉด ์ธ์ ๋ ํผ๋๋ฐฑ ์ฃผ์๋ฉด ๋ฐ๋ก ๋ฐ์ํ๊ฒ ์ต๋๋ค..!
์์ ์ฟผ๋ฆฌ
SELECT p
FROM Post p
WHERE p.id NOT IN :postIds
์ ์ฟผ๋ฆฌ๋ ํน์ ID ๋ชฉ๋ก(:postIds)์ ํฌํจ๋์ง ์์ ๊ฒ์๊ธ(Post)๋ฅผ ์กฐํํ๋ ์์ฃผ ์ง๊ด์ ์ธ ๋ฐฉ์์
๋ฐ์ํ ์ ์๋ ๋ฌธ์ ์
1. ์ ์ฒด ํ ์ด๋ธ ์ค์บ (Full Table Scan), ์ธ๋ฑ์ค ํ ์ค์บ(Full Index Scan)
NOT IN์ ๋ถ์ ์กฐ๊ฑด์ด๋ผ์ DB ์ตํฐ๋ง์ด์ ๊ฐ ํจ์จ์ ์ธ ์คํ ๊ณํ์ ์ธ์ฐ๊ธฐ ์ด๋ ค์
=> ์ ์ฒด ํ ์ด๋ธ ์ค์บ์ด๋ ์ธ๋ฑ์ค ํ ์ค์บ์ ์ ๋ฐํจ
DB ์ตํฐ๋ง์ด์ ๋ SQL ์ฟผ๋ฆฌ๋ฅผ ์คํํ ๋, ๊ฐ์ฅ ๋น ๋ฅด๊ณ ํจ์จ์ ์ธ ์คํ ๊ณํ์ ์ธ์ฐ๋ DB์ ๋๋๊ฐ์ ์ญํ ์
DB๋ ๋จ์ํ ์ฟผ๋ฆฌ๋ฅผ ๊ทธ๋๋ก ์คํํ์ง ์๊ณ ๋ด๋ถ์ ์ผ๋ก ์ด๊ฑธ ์ด๋ค ์์๋ก, ์ด๋ค ์ธ๋ฑ์ค๋ฅผ ์จ์ ์คํํ ๊น๋ฅผ ๊ณ์ฐํ๋๋ฐ
์ด ๊ณผ์ ์ Query Optimizer๊ฐ ์ํํจ
NOT IN์ ์ ์ฒด ๋ฐ์ดํฐ๋ ํ ์ด๋ธ์ ์ค์บํ ํ ์กฐ๊ฑด์ ๋ง์ง ์๋ ๋ ์ฝ๋๋ฅผ ํํฐ๋ง ํ๋ ๋ถ์ ์กฐ๊ฑด์ด๊ธฐ์ DB ์ตํฐ๋ง์ด์ ๊ฐ ํจ์จ์ ์ธ ์คํ ๊ณํ์ ์ธ์ฐ๊ธฐ ์ด๋ ค์
2. ์ธ๋ฑ์ค ํ์ฉ ์ด๋ ค์
IN์ ์ธ๋ฑ์ค Range Scan์ ํตํด ๋น ๋ฅด๊ฒ ์กฐํํ ์ ์์ง๋ง, NOT IN์ ์ธ๋ฑ์ค ํ์ฉ๋๊ฐ ํ์ ํ ๋จ์ด์ง
(NOT IN์ ์ธ๋ฑ์ค ๋ณด๋ค ๋๋ฆฐ Full Scan์ด๋ Full Index Scan์ ์ ๋ฐํ๊ธฐ ๋๋ฌธ)
3. NULL ํฌํจ ์ ์๋์น ์์ ๊ฒฐ๊ณผ
NULL ๊ฐ ์ฒ๋ฆฌ ๋ก์ง์ผ๋ก ์ธํ ์์์น ๋ชปํ ๊ฒฐ๊ณผ๊ฐ ๋ฐ์ํ ์ ์์
=> NULL ๊ณผ์ ๋น๊ต๋ UNKNOWN์ด ๋์ด ๋ถ์ผ์น๋ก ๊ฐ์ฃผ๋๊ธฐ ๋๋ฌธ์ column NOT IN (1, 2, NULL) ์ ํญ์ ๋น ๊ฒฐ๊ณผ๋ฅผ ๋ฐํํจ
4. ๋ง์ ๊ฐ์ด ๋ค์ด์ฌ ๋ ์ค๋ฒํค๋
์์ ์์ ์ฟผ๋ฆฌ์์ :postIds์ ์์ฒ ๊ฐ์ ID๊ฐ ๋ค์ด์ค๋ฉด ํ์ฑ, ์ต์ ํ, ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ ์ธก๋ฉด์์ ๋ถ๋ด์ด ์ปค์ง
(๋๋์ ๊ฐ์ IN ์ ์ ๋ฃ์ผ๋ฉด ์คํ ๊ณํ ์์ฑ์ด ๋์ด๋๊ณ , ํ์ฑ ๋ฐ ์ต์ ํธ ๋จ๊ณ์์ ์ถ๊ฐ์ ์ธ ์ค๋ฒํค๋๊ฐ ๋ฐ์ํจ)
์ต์ ํ ๋ฐฉ์
NOT EXISTS ์ฌ์ฉ
SELECT p
FROM Post p
WHERE NOT EXISTS (
SELECT 1
FROM Post temp
WHERE temp.id = p.id AND temp.id IN :postIds
)
NOT EXISTS๋ ํ ๋จ์๋ก ์กฐ๊ฑด์ ๊ฒ์ฌํ๊ณ , ์กฐ๊ฑด์ ๋ง์กฑํ๋ฉด(๋งค์นญ๋๋ ์ฒซ ํ์ ์ฐพ์๋ง์) ๋ฐ๋ก exitํจ
=> DBMS๊ฐ ์กด์ฌํ์ง ์์ ์ ํ์ธํ๊ธฐ ์ํด ํน๋ณํ ์ต์ ํ๋ ๋ฐฉ์์
์ด๋ ์ธ๋ฑ์ค ํ์ฉ์ด ๋ ์ ๋ฆฌํ๊ณ , ํ์ฅ์ฑ ์ข์ ์ฟผ๋ฆฌ์ด๋ฉฐ NULL ๊ฐ์ด ํฌํจ๋์ด๋ ์ ํํ๊ฒ ์ฒ๋ฆฌ๋จ
(๋๊ท๋ชจ ๋ฐ์ดํฐ์
์์ ๊ฐ์ฅ ์์ ์ ์ด๊ณ ํ์ฅ์ฑ ์๋ ์ฑ๋ฅ์ ์ ๊ณตํจ)
LEFT JOIN + IS NULL ์ฌ์ฉ
SELECT p
FROM Post p
LEFT JOIN (
SELECT temp.id
FROM Post temp
WHERE temp.id IN :postIds
) filtered ON p.id = filtered.id
WHERE filtered.id IS NULL
์๋ ๋ฐฉ์์ ์ดํด๋ณด๋ฉด Post ํ ์ด๋ธ์์ ์กฐ๊ฑด์ ๋ง๋ ID๋ค๋ง ์ถ๋ฆฐ ์๋ธ์ฟผ๋ฆฌ filtered๋ฅผ ๋ง๋ค๊ณ LEFT JOINํจ
์ด ๋ p.id๊ฐ :postIds์ ํฌํจ๋๋ฉด ๋งค์นญ๋๋ filtered.id๊ฐ ์๊ณ NULL์ด ์๋์ง๋ง ๋ง์ฝ p.id๊ฐ :postIds์ ์์ผ๋ฉด ๋งค์นญ์ด ๋์ง ์๊ณ filtered.id๊ฐ NULL์ด ๋ ๊ฒ์
=> filtered.id์ IS NULL ์กฐ๊ฑด์ ์ฌ์ฉํ์ฌ :postIds์ ํฌํจ๋์ง ์์ p.id๋ง ๋จ๊น
์๋ธ์ฟผ๋ฆฌ๊ฐ ์์ ๋ ์์ฃผ ๋น ๋ฅด๊ณ
(JOIN ๋์์ด ์์์ง๋ฉด JOIN ์ฐ์ฐ ์ ๋น๊ตํ row ์๊ฐ ์ค์ด๋ค์ด ์ฒ๋ฆฌ ์๋๊ฐ ๋นจ๋ผ์ง)
JOIN์ PK ์ธ๋ฑ์ค๊ฐ ์์ผ๋ฉด ์ต์ ํ ํจ๊ณผ๊ฐ ํผ
PK๋ ๋ฌด์กฐ๊ฑด ์ ์ผํ ๊ฐ์ด 1๊ฐ์ด๋ฏ๋ก JOIN, WHERE ์กฐ๊ฑด์์ ์ ํํ 1๊ฑด(์ต๋ 1๊ฐ)๋ง ์ฐพ์ผ๋ฉด ๋๋จ
=> ์ตํฐ๋ง์ด์ ๊ฐ ๊ฐ์ฅ ๋น ๋ฅธ ์๊ณ ๋ฆฌ์ฆ(Index Seek) ์ ํ ๊ฐ๋ฅ
์ผ๋ฐ ์ธ๋ฑ์ค๋ ์ค๋ณต ๋ฐ์ดํฐ๊ฐ ์์ ์ ์์ด์ ๊ฐ์ ์กฐ๊ฑด์ ํด๋นํ๋ ๋ ์ฝ๋๋ฅผ ์ฌ๋ฌ ๊ฐ ์ฐพ์์ผ ํ ์ ๋ ์์
=> ์ตํฐ๋ง์ด์ ๋ ์ถ๊ฐ๋ก ํ ์ด๋ธ ์ ๊ทผ(lookup) ํ์
๋ง์ฝ postIds๊ฐ ๋ง๋ค๋ฉด?
- SQL ์ฟผ๋ฆฌ ๊ธธ์ด ์ ํ ๋ฌธ์
- IN ์์ ์ ์ฒ ๊ฐ ๊ฐ์ด ๋ค์ด๊ฐ๋ฉด ์ตํฐ๋ง์ด์ ๊ฐ ์ฒ๋ฆฌ ์ ๋ต์ ์ ํ๊ธฐ ํ๋ค์ด์ง๋ฏ๋ก Full Table Scan์ ์ ํํ๊ฑฐ๋ ํ์ฑ ์๋ ๋ฐ ๋คํธ์ํฌ ํธ๋ํฝ ์ฆ๊ฐ๊ฐ ์๊น
- Hibernate๋ IN์ ํ๋ผ๋ฏธํฐ๊ฐ ๋๋ฌด ๋ง์ผ๋ฉด ์์ธ ๋ฐ์ํจ
(QueryParameterBindingException)
์์ ๊ฐ์ ๋ฌธ์ ๋ค์ด ๋ฐ์ํ ์ ์๊ธฐ์
์์ ํ ์ด๋ธ์ ์ ์ฅ + JOIN
-- 1. postIds๋ฅผ ์์ ํ
์ด๋ธ(PostIdsTemp)์ insert
-- 2. JOIN์ผ๋ก ์ฒ๋ฆฌ
SELECT p.*
FROM Post p
JOIN PostIdsTemp pid ON p.id = pid.id
์์ ์์ ํ ์ด๋ธ์ ์ ์ฅํ๊ณ JOIN์ผ๋ก ์ฒ๋ฆฌํ๋ ๊ฒ์ด ๋ ์์ ํ ์ ์์
(JOIN์ ์ธ๋ฑ์ค๋ฅผ ํ ์ ์์ด ๋น ๋ฅด๊ณ postIds ๊ฐ์์ ์ ํ์ด ์์)
๋ฐฐ์น ์ฒ๋ฆฌ
// postIds๊ฐ 5000๊ฐ๋ฉด โ 1000๊ฐ์ฉ 5๋ฒ ๋๋ ์ 5๋ฒ ์ฟผ๋ฆฌ ์คํ
for (List<Long> batch : batchSplit(postIds, 1000)) {
query.setParameter("postIds", batch).getResultList();
}
Hibernate/JPA์์๋ IN/NOT IN ์ฌ์ฉ ์ ์ปฌ๋ ์ ์ด ๋๋ฌด ํฌ๋ฉด ์ฟผ๋ฆฌ๋ฅผ ๋๋ ์ ๋ฐฐ์น ์ฒ๋ฆฌ๋ฅผ ๊ณ ๋ คํ ์ ์์
์ด๋ ๊ฒ ํ๋ฉด ์ฟผ๋ฆฌ ๊ธธ์ด ์ ํ์ ์ฐํํ ์ ์๊ณ Hibernate ๋ด๋ถ ์ ์ฝ๋ ํผํ ์ ์๋๋ฐ ํด๋ผ์ด์ธํธ-์๋ฒ ๊ฐ ํต์ ํ์๊ฐ ๋์ด๋๋ฏ๋ก ์ด ์๋ต ์๊ฐ์ ์ฃผ์ํด์ผํ๊ณ ๊ฒฐ๊ณผ๋ฅผ ์ง์ merge/์ค๋ณต ์ ๊ฑฐ ํด์ผ๋ ์ ๋ ์์
Native SQL๋ก ์ง์ ์ฒ๋ฆฌ
@Query(value = "SELECT * FROM post p WHERE p.id IN (SELECT id FROM temp_ids)", nativeQuery = true)
JPA์ JPQL์ ๋ด๋ถ์ ์ผ๋ก ์์ ์ฅ์น๊ฐ ๋ง๊ณ , ๋ณต์กํ ์ต์ ํ๋ฅผ ํ๊ธฐ ์ด๋ ต๊ธฐ์ ์ฑ๋ฅ์ด ์ค์ํ ์ฟผ๋ฆฌ๋ ์์ Native SQL๋ก ์ง์ ์์ฑํ์ฌ ์ต์ ํํ๋ ๊ฒ๋ ๊ณ ๋ คํด ๋ณด๋๊ฒ ์ข์
'๐ซง Database > SQL' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
๋ฐ์ดํฐ ๋ฐ ํ ์ด๋ธ ์กฐ์ (0) | 2024.02.29 |
---|---|
ํ์ ์ฟผ๋ฆฌ (2) | 2024.02.29 |
ํ ์ด๋ธ ํฉ์น๊ธฐ (1) | 2024.02.29 |
๋ฐ์ดํฐ์ ๊ทธ๋ฃนํ, ํํฐ๋ง (1) | 2024.02.27 |
SQL ํจ์ ํ์ฉํ๊ธฐ (0) | 2024.02.26 |
๋งค์ผ๋ฉ์ผ ๋ฐฑ์๋ ์ง๋ฌธ์ ์ฐธ๊ณ ํด ๊ฐ์ธ์ ์ผ๋ก ํ์ตํ ๋ด์ฉ์ ์ ๋ฆฌํ์์ต๋๋ค.
์ค๋ฅ๊ฐ ์๋ค๋ฉด ์ธ์ ๋ ํผ๋๋ฐฑ ์ฃผ์๋ฉด ๋ฐ๋ก ๋ฐ์ํ๊ฒ ์ต๋๋ค..!
์์ ์ฟผ๋ฆฌ
SELECT p
FROM Post p
WHERE p.id NOT IN :postIds
์ ์ฟผ๋ฆฌ๋ ํน์ ID ๋ชฉ๋ก(:postIds)์ ํฌํจ๋์ง ์์ ๊ฒ์๊ธ(Post)๋ฅผ ์กฐํํ๋ ์์ฃผ ์ง๊ด์ ์ธ ๋ฐฉ์์
๋ฐ์ํ ์ ์๋ ๋ฌธ์ ์
1. ์ ์ฒด ํ ์ด๋ธ ์ค์บ (Full Table Scan), ์ธ๋ฑ์ค ํ ์ค์บ(Full Index Scan)
NOT IN์ ๋ถ์ ์กฐ๊ฑด์ด๋ผ์ DB ์ตํฐ๋ง์ด์ ๊ฐ ํจ์จ์ ์ธ ์คํ ๊ณํ์ ์ธ์ฐ๊ธฐ ์ด๋ ค์
=> ์ ์ฒด ํ ์ด๋ธ ์ค์บ์ด๋ ์ธ๋ฑ์ค ํ ์ค์บ์ ์ ๋ฐํจ
DB ์ตํฐ๋ง์ด์ ๋ SQL ์ฟผ๋ฆฌ๋ฅผ ์คํํ ๋, ๊ฐ์ฅ ๋น ๋ฅด๊ณ ํจ์จ์ ์ธ ์คํ ๊ณํ์ ์ธ์ฐ๋ DB์ ๋๋๊ฐ์ ์ญํ ์
DB๋ ๋จ์ํ ์ฟผ๋ฆฌ๋ฅผ ๊ทธ๋๋ก ์คํํ์ง ์๊ณ ๋ด๋ถ์ ์ผ๋ก ์ด๊ฑธ ์ด๋ค ์์๋ก, ์ด๋ค ์ธ๋ฑ์ค๋ฅผ ์จ์ ์คํํ ๊น๋ฅผ ๊ณ์ฐํ๋๋ฐ
์ด ๊ณผ์ ์ Query Optimizer๊ฐ ์ํํจ
NOT IN์ ์ ์ฒด ๋ฐ์ดํฐ๋ ํ ์ด๋ธ์ ์ค์บํ ํ ์กฐ๊ฑด์ ๋ง์ง ์๋ ๋ ์ฝ๋๋ฅผ ํํฐ๋ง ํ๋ ๋ถ์ ์กฐ๊ฑด์ด๊ธฐ์ DB ์ตํฐ๋ง์ด์ ๊ฐ ํจ์จ์ ์ธ ์คํ ๊ณํ์ ์ธ์ฐ๊ธฐ ์ด๋ ค์
2. ์ธ๋ฑ์ค ํ์ฉ ์ด๋ ค์
IN์ ์ธ๋ฑ์ค Range Scan์ ํตํด ๋น ๋ฅด๊ฒ ์กฐํํ ์ ์์ง๋ง, NOT IN์ ์ธ๋ฑ์ค ํ์ฉ๋๊ฐ ํ์ ํ ๋จ์ด์ง
(NOT IN์ ์ธ๋ฑ์ค ๋ณด๋ค ๋๋ฆฐ Full Scan์ด๋ Full Index Scan์ ์ ๋ฐํ๊ธฐ ๋๋ฌธ)
3. NULL ํฌํจ ์ ์๋์น ์์ ๊ฒฐ๊ณผ
NULL ๊ฐ ์ฒ๋ฆฌ ๋ก์ง์ผ๋ก ์ธํ ์์์น ๋ชปํ ๊ฒฐ๊ณผ๊ฐ ๋ฐ์ํ ์ ์์
=> NULL ๊ณผ์ ๋น๊ต๋ UNKNOWN์ด ๋์ด ๋ถ์ผ์น๋ก ๊ฐ์ฃผ๋๊ธฐ ๋๋ฌธ์ column NOT IN (1, 2, NULL) ์ ํญ์ ๋น ๊ฒฐ๊ณผ๋ฅผ ๋ฐํํจ
4. ๋ง์ ๊ฐ์ด ๋ค์ด์ฌ ๋ ์ค๋ฒํค๋
์์ ์์ ์ฟผ๋ฆฌ์์ :postIds์ ์์ฒ ๊ฐ์ ID๊ฐ ๋ค์ด์ค๋ฉด ํ์ฑ, ์ต์ ํ, ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ ์ธก๋ฉด์์ ๋ถ๋ด์ด ์ปค์ง
(๋๋์ ๊ฐ์ IN ์ ์ ๋ฃ์ผ๋ฉด ์คํ ๊ณํ ์์ฑ์ด ๋์ด๋๊ณ , ํ์ฑ ๋ฐ ์ต์ ํธ ๋จ๊ณ์์ ์ถ๊ฐ์ ์ธ ์ค๋ฒํค๋๊ฐ ๋ฐ์ํจ)
์ต์ ํ ๋ฐฉ์
NOT EXISTS ์ฌ์ฉ
SELECT p
FROM Post p
WHERE NOT EXISTS (
SELECT 1
FROM Post temp
WHERE temp.id = p.id AND temp.id IN :postIds
)
NOT EXISTS๋ ํ ๋จ์๋ก ์กฐ๊ฑด์ ๊ฒ์ฌํ๊ณ , ์กฐ๊ฑด์ ๋ง์กฑํ๋ฉด(๋งค์นญ๋๋ ์ฒซ ํ์ ์ฐพ์๋ง์) ๋ฐ๋ก exitํจ
=> DBMS๊ฐ ์กด์ฌํ์ง ์์ ์ ํ์ธํ๊ธฐ ์ํด ํน๋ณํ ์ต์ ํ๋ ๋ฐฉ์์
์ด๋ ์ธ๋ฑ์ค ํ์ฉ์ด ๋ ์ ๋ฆฌํ๊ณ , ํ์ฅ์ฑ ์ข์ ์ฟผ๋ฆฌ์ด๋ฉฐ NULL ๊ฐ์ด ํฌํจ๋์ด๋ ์ ํํ๊ฒ ์ฒ๋ฆฌ๋จ
(๋๊ท๋ชจ ๋ฐ์ดํฐ์
์์ ๊ฐ์ฅ ์์ ์ ์ด๊ณ ํ์ฅ์ฑ ์๋ ์ฑ๋ฅ์ ์ ๊ณตํจ)
LEFT JOIN + IS NULL ์ฌ์ฉ
SELECT p
FROM Post p
LEFT JOIN (
SELECT temp.id
FROM Post temp
WHERE temp.id IN :postIds
) filtered ON p.id = filtered.id
WHERE filtered.id IS NULL
์๋ ๋ฐฉ์์ ์ดํด๋ณด๋ฉด Post ํ ์ด๋ธ์์ ์กฐ๊ฑด์ ๋ง๋ ID๋ค๋ง ์ถ๋ฆฐ ์๋ธ์ฟผ๋ฆฌ filtered๋ฅผ ๋ง๋ค๊ณ LEFT JOINํจ
์ด ๋ p.id๊ฐ :postIds์ ํฌํจ๋๋ฉด ๋งค์นญ๋๋ filtered.id๊ฐ ์๊ณ NULL์ด ์๋์ง๋ง ๋ง์ฝ p.id๊ฐ :postIds์ ์์ผ๋ฉด ๋งค์นญ์ด ๋์ง ์๊ณ filtered.id๊ฐ NULL์ด ๋ ๊ฒ์
=> filtered.id์ IS NULL ์กฐ๊ฑด์ ์ฌ์ฉํ์ฌ :postIds์ ํฌํจ๋์ง ์์ p.id๋ง ๋จ๊น
์๋ธ์ฟผ๋ฆฌ๊ฐ ์์ ๋ ์์ฃผ ๋น ๋ฅด๊ณ
(JOIN ๋์์ด ์์์ง๋ฉด JOIN ์ฐ์ฐ ์ ๋น๊ตํ row ์๊ฐ ์ค์ด๋ค์ด ์ฒ๋ฆฌ ์๋๊ฐ ๋นจ๋ผ์ง)
JOIN์ PK ์ธ๋ฑ์ค๊ฐ ์์ผ๋ฉด ์ต์ ํ ํจ๊ณผ๊ฐ ํผ
PK๋ ๋ฌด์กฐ๊ฑด ์ ์ผํ ๊ฐ์ด 1๊ฐ์ด๋ฏ๋ก JOIN, WHERE ์กฐ๊ฑด์์ ์ ํํ 1๊ฑด(์ต๋ 1๊ฐ)๋ง ์ฐพ์ผ๋ฉด ๋๋จ
=> ์ตํฐ๋ง์ด์ ๊ฐ ๊ฐ์ฅ ๋น ๋ฅธ ์๊ณ ๋ฆฌ์ฆ(Index Seek) ์ ํ ๊ฐ๋ฅ
์ผ๋ฐ ์ธ๋ฑ์ค๋ ์ค๋ณต ๋ฐ์ดํฐ๊ฐ ์์ ์ ์์ด์ ๊ฐ์ ์กฐ๊ฑด์ ํด๋นํ๋ ๋ ์ฝ๋๋ฅผ ์ฌ๋ฌ ๊ฐ ์ฐพ์์ผ ํ ์ ๋ ์์
=> ์ตํฐ๋ง์ด์ ๋ ์ถ๊ฐ๋ก ํ ์ด๋ธ ์ ๊ทผ(lookup) ํ์
๋ง์ฝ postIds๊ฐ ๋ง๋ค๋ฉด?
- SQL ์ฟผ๋ฆฌ ๊ธธ์ด ์ ํ ๋ฌธ์
- IN ์์ ์ ์ฒ ๊ฐ ๊ฐ์ด ๋ค์ด๊ฐ๋ฉด ์ตํฐ๋ง์ด์ ๊ฐ ์ฒ๋ฆฌ ์ ๋ต์ ์ ํ๊ธฐ ํ๋ค์ด์ง๋ฏ๋ก Full Table Scan์ ์ ํํ๊ฑฐ๋ ํ์ฑ ์๋ ๋ฐ ๋คํธ์ํฌ ํธ๋ํฝ ์ฆ๊ฐ๊ฐ ์๊น
- Hibernate๋ IN์ ํ๋ผ๋ฏธํฐ๊ฐ ๋๋ฌด ๋ง์ผ๋ฉด ์์ธ ๋ฐ์ํจ
(QueryParameterBindingException)
์์ ๊ฐ์ ๋ฌธ์ ๋ค์ด ๋ฐ์ํ ์ ์๊ธฐ์
์์ ํ ์ด๋ธ์ ์ ์ฅ + JOIN
-- 1. postIds๋ฅผ ์์ ํ
์ด๋ธ(PostIdsTemp)์ insert
-- 2. JOIN์ผ๋ก ์ฒ๋ฆฌ
SELECT p.*
FROM Post p
JOIN PostIdsTemp pid ON p.id = pid.id
์์ ์์ ํ ์ด๋ธ์ ์ ์ฅํ๊ณ JOIN์ผ๋ก ์ฒ๋ฆฌํ๋ ๊ฒ์ด ๋ ์์ ํ ์ ์์
(JOIN์ ์ธ๋ฑ์ค๋ฅผ ํ ์ ์์ด ๋น ๋ฅด๊ณ postIds ๊ฐ์์ ์ ํ์ด ์์)
๋ฐฐ์น ์ฒ๋ฆฌ
// postIds๊ฐ 5000๊ฐ๋ฉด โ 1000๊ฐ์ฉ 5๋ฒ ๋๋ ์ 5๋ฒ ์ฟผ๋ฆฌ ์คํ
for (List<Long> batch : batchSplit(postIds, 1000)) {
query.setParameter("postIds", batch).getResultList();
}
Hibernate/JPA์์๋ IN/NOT IN ์ฌ์ฉ ์ ์ปฌ๋ ์ ์ด ๋๋ฌด ํฌ๋ฉด ์ฟผ๋ฆฌ๋ฅผ ๋๋ ์ ๋ฐฐ์น ์ฒ๋ฆฌ๋ฅผ ๊ณ ๋ คํ ์ ์์
์ด๋ ๊ฒ ํ๋ฉด ์ฟผ๋ฆฌ ๊ธธ์ด ์ ํ์ ์ฐํํ ์ ์๊ณ Hibernate ๋ด๋ถ ์ ์ฝ๋ ํผํ ์ ์๋๋ฐ ํด๋ผ์ด์ธํธ-์๋ฒ ๊ฐ ํต์ ํ์๊ฐ ๋์ด๋๋ฏ๋ก ์ด ์๋ต ์๊ฐ์ ์ฃผ์ํด์ผํ๊ณ ๊ฒฐ๊ณผ๋ฅผ ์ง์ merge/์ค๋ณต ์ ๊ฑฐ ํด์ผ๋ ์ ๋ ์์
Native SQL๋ก ์ง์ ์ฒ๋ฆฌ
@Query(value = "SELECT * FROM post p WHERE p.id IN (SELECT id FROM temp_ids)", nativeQuery = true)
JPA์ JPQL์ ๋ด๋ถ์ ์ผ๋ก ์์ ์ฅ์น๊ฐ ๋ง๊ณ , ๋ณต์กํ ์ต์ ํ๋ฅผ ํ๊ธฐ ์ด๋ ต๊ธฐ์ ์ฑ๋ฅ์ด ์ค์ํ ์ฟผ๋ฆฌ๋ ์์ Native SQL๋ก ์ง์ ์์ฑํ์ฌ ์ต์ ํํ๋ ๊ฒ๋ ๊ณ ๋ คํด ๋ณด๋๊ฒ ์ข์
'๐ซง Database > SQL' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
๋ฐ์ดํฐ ๋ฐ ํ ์ด๋ธ ์กฐ์ (0) | 2024.02.29 |
---|---|
ํ์ ์ฟผ๋ฆฌ (2) | 2024.02.29 |
ํ ์ด๋ธ ํฉ์น๊ธฐ (1) | 2024.02.29 |
๋ฐ์ดํฐ์ ๊ทธ๋ฃนํ, ํํฐ๋ง (1) | 2024.02.27 |
SQL ํจ์ ํ์ฉํ๊ธฐ (0) | 2024.02.26 |