본문 바로가기

use-the-index-luke

5.Select * is Bad

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/blog/2013-08/its-not-about-the-star-stupid

select * 는 평판이 좋지 않습니다.

대부분의 사람들은 테이블 정의의 변경으로 인해 탐지하기 어려운 버그가 발생하기 때문이라고 생각합니다.

모든 열을 원하는 순서대로 나열하면 문제가 해결되는 거죠? 네, 하지만 그렇다고 해서 select *의 두번째 문제가 해결되지는 않습니다.

또 다른 문제는 열을 더 요청하면 데이터베이스 작업이 더 많아진다는 것입니다.

놀라운 것은 성능에 미치는 영향이 클 수 있다는 점입니다.


Up to 100x slower when preventing an Index-Only Scan

일반적으로, 요청하는 열이 적을수록 쿼리를 처리할 때 디스크에서 로드해야 하는 데이터가 줄어듭니다. 그러나 이 관계는 비선형적입니다.

테이블에서 선택하는 데는

(1) 인덱스를 사용하여 선택한 행이 저장된 주소를 찾고, (2) 테이블에서 선택한 행을 로드하는 두 가지 단계가 수반되는 경우가 많습니다.

이제 인덱스에 있는 열만 선택하다고 가정해 보십시오. 데이터베이스가 여전히 두 번째 단계를 수행해야 하는 이유는 무엇입니까? 사실 대분의 데이터베이스는 그렇지 않습니다. 인덱스에 저장된 정보만 사용하여 쿼리를 처리할 수 있으므로 인덱스만 검색할 수 있습니다.

하지만 인덱스 전용 검색이 100배 더 빨라야 하는 이유는 무엇입니까?

단순: 이상적인 인덱스는 선택한 행을 서로 옆에 저장합니다. 각 인덱스 페이지에 약 100개의 행이 있는 것은 드문일이 아닙니다.

즉, 대략적인 수치입니다. 인덱스된 열의 크기에 따라 다릅니다. 그럼에도 불구하고 IO 작업 하나가 100개의 행을 가져올 수 있음을 의미합니다.

그러나 테이블 데이터는 그렇게 구성되어 있지 않습니다(예외). 여기서 페이지에는 선택한 행 중 하나와 특정 쿼리에 관심이 없는 다른 많은 행이 포함되어 있는 것이 일반적입니다. 인덱스 전용 검색이 100배 더 빠를 수 있는 이유는 인덱스 액세스가 IO당 100개의 행을 쉽게 제공할 수 있는 반면 테이블 액세스는 일반적으로 IO당 몇 개의 행만 가져올 수 있기 때문입니다.

인덱스에 없는 열을 하나만 선택하면 데이터베이스는 Index-only scan을 수행할 수 없습니다. 만약 당신이 모든 열을 선택한다면, 저는 당신이 담을 알고 있다고 생각합니다.

또한 일부 데이터베이스는 큰 개체를 별도의 위치(예: Oracle 의 LOB)에 저장합니다.

이러한 데이터에 액세스하면 추가 IO도 발생합니다.



Up to 5x slower when bloating server memory footprint

데이터베이스는 결과를 서버의 기본 메모리에 저장하는 것을 피하지만, 로드 후 각행을 전달하고 다시 잊어버리는 대신, 결과를 저장하는 것이 불가피한 경우가 있습니다. 예를 들어 정렬을 수행하려면 모든 행과 선택한 모든 열을 메모리에 저장해야 합니다. 다시 한 번 말하지만, 더 많은 열을 선택할 수록 데이터베이스에 더 많은 메모리가 필요합니다. 최악의 경우 데이터베이스가 디스크에서 외부 정렬을 수행해야 할 수도 있습니다.

그러나 대부분의 데이터베이스는 이러한 종류의 워크로드에 매우 적합합니다.

사용하지 않는 몇 개의 열을 제거하는 것만으로 2배를 정렬하는 속도가 빨라지는 것을 꽤 자주 보았지만 5배를 초과한 경우는 기억나지 않습니다.

그러나, 이것은 단순히 정렬하는 것이 아니라, 해시 조인도 메모리 블롯에 다소 민감합니다.

그게 뭔지 모르시나요? 이 게시글을 읽어주세요.


이것들은 데이터베이스 관점에서 볼 때 가장 중요한 두 가지 문제일 뿐입니다. 네트워크에도 문제가 발생하고 클라이언트도 데이터를 처리해야 하므로 garbage collection에 상당한 부담이 될 수 있습니다.

많은 사람들은 그 별이 나쁜 것이라고 생각합니다.

따라서 ORM이 모든 열을 이름별로 나열하더라도 문제가 없다고 생각합니다. 사실, 범죄는 생각하지 않고 모든 열을 선택하는 것입니다. 대부분은 ORM은 사용자를 대신하여 이러한 범죄를 쉽게 저지릅니다.

우리가 "select * is bad" 라고 말할 때, 우리는 별을 "생각하지 않고 모든 것을 선택"하는 기호로 사용합니다.

이것이 나쁜것입니다. 이름 기억하기 위해 더많은 캐치프라이즈가 필요한 경우 다음과 같이 하십시오:


스타(*)때문이 아니야, 멍청아!


제가 설명하는 방식이 마음에 드신다면, 제 책

*SQL Performance Explained*가 마음에 드실 겁니다.

'use-the-index-luke' 카테고리의 다른 글

D.1 Execution Plan  (0) 2024.02.26
D.Glossary  (0) 2024.02.22
4.Dynamic SQL is Slow  (0) 2024.02.15
3.Oracle Cannot Index NULL  (0) 2024.02.12
2.Most Selective First  (0) 2024.02.08