데이터베이스 인덱스를 추가하는 것이 조기 최적화입니까?


61

오늘 내 동료는 애플리케이션의 모든 쿼리를 검토하고 그에 따라 인덱스를 추가 할 것을 제안했습니다.

우리 응용 프로그램이 아직 출시되지 않았기 때문에 이것이 조기 최적화라고 생각합니다. 나는 우리가 라이브에 들어간 후 느린 쿼리를 모니터링하고 그에 따라 인덱스를 추가 할 것을 제안했습니다.

데이터베이스를 설계 할 때 일반적인 합의는 무엇입니까? 새 쿼리를 작성할 때마다 일치하는 인덱스를 추가해야합니까? 아니면 모니터링하고 어떻게 진행하는지 보는 것이 낫습니까?


32
그것은 의견의 문제 일지 모르지만 일부 색인을 사전에 추가 할 수 있다고 생각합니다 .
Basile Starynkevitch

2
@BasileStarynkevitch 우리가 이미 기본 키 인덱스와 작업을 가지고 있다는 것에 완전히 동의합니다. 그러나 선을 어디에 그리십니까?
Marco de Jongh

1
경험에서 얻은 2 센트 : 데이터베이스의 하위 집합에서 일부 초기 검색 쿼리를 테스트하고있었습니다. 내가 실행 한 테스트는 내 로컬 사본에서 완전히 괜찮 았습니다. 그런 다음 응용 프로그램을 전체 데이터베이스를 호스팅하는 준비 영역으로 푸시했습니다. 내 테스트는 <500ms 동안 실행되었지만 준비 시스템은 해결하는 데 몇 분이 걸렸습니다 . 내 상사는 왜 앱이로드되지 않는지에 대해 완전히 혼란스러워했습니다. 설명 유형 작업은 당신의 친구입니다 ... 적어도 큰 테이블에서 순차적 스캔을 찾아보십시오!
Chris Cirefice

2
인덱스를 추가하지 않는 것은 bubblesort를 사용하는 것과 같습니다. 가장 자주 테스트 할 때 아무런 문제도 발견하지 못하지만 프로그램이 실시간으로 확장되기 시작하면 많은 문제가 발생합니다. 그리고 인덱스는 속도 차이에서 쉽게 계수 100을 만들 수 있습니다.
피터 B

3
항상 기억하십시오 : 색인은 쿼리 속도를 높이는 마술이 아닙니다. 인덱스는 대부분의 DML 작업에서 비용을 발생 시키며 유형에 따라 많은 사람들이 동일한 테이블을 업데이트 할 때 대기 시간이 길어질 수 있습니다. 쿼리 : FTS가 가장 빠르거나 파티셔닝이 모든 작업을 수행하는 인덱스에서 전혀 도움이되지 않는 쿼리가 많이 있습니다. -도움이 될만한 인덱스 만 추가하십시오!
팔코

답변:


132

조기 최적화는 애매 모호하고 직관적 인 감각으로 인해 무언가를 "최적화"하고 있는데, 이는 특히 코드 가독성 및 유지 관리 성 이 저하 될 수 있기 때문에 아마도 느릴 것입니다 . 성능과 관련하여 잘 확립 된 모범 사례를 의도적으로 따르지 않는 것은 아닙니다.

때때로 그것은 그리기 어려운 선이지만, 라이브에 가기 전에 인덱스를 추가하지 않는 것이 너무 늦은 최적화 라고 분명히 말하고 싶습니다 . 이는 가장 열성적이고 가장 중요한 사용자 인 얼리 어답터를 처벌하고 제품에 대한 부정적인 견해를 제공하여 검토, 토론 등으로 확산 될 것입니다. 쿼리를 모니터링하여 인덱싱이 필요한 문제를 해결하는 것은 좋은 생각이지만, 베타 버전 이후에는 그렇게해야합니다.


11
예,로드 테스트 단계에서 수행해야합니다
Alvaro

152
느린 부품이 어디에 있는지 알기 전에 최적화하는 것이 조기에 최적화됩니다. 느린 부품이 어디에 있는지 알기 전에 먼저 물건을 풀어 놓으십시오 .
MathematicalOrchid

4
@MathematicalOrchid : 좋은 표현입니다! 다른 곳에서 빌려도 될까요?
Pieter Geerkens

3
@PieterGeerkens 물론입니다. ;-) 91 세 이상의 공감대가 저에게 어떤 대리도 얻지 못한다는 것이 유감입니다.
MathematicalOrchid

3
@MathematicalOrchid가 답이되어야합니다. "가장 작은 직진 점"에 대한 답을 얻을 수 있습니다.
Mindwin

48

라이브로 이동하면 느린 쿼리를 모니터링

사용자에게 디자인 부족으로 고통을주는 것과 같은 품질은 없습니다!

테이블을 디자인 할 때 인덱스가 필요한 쿼리를 알고 있어야하며 where 절과 조인에서 쿼리 할 열을 알고 있어야합니다. 실제 환경에서는 명백하지 않은 것이 저장된 부 하나 데이터가 증가 할 때 빠르게 명백해질 수 있기 때문에 이미 색인화되어야합니다. 이것이 일어날 때 원하지 않는 것은 모든 '느린'쿼리에서 인덱스를 때리는 것입니다. 모든 것에 대한 인덱스로 끝납니다.


10
권리. 데이터베이스 디자인의 일부로 인덱스를 고려하십시오. 최종 사용자가 일반적으로 실시간으로 수행하는 쿼리에 대한 전체 테이블 스캔을 피하려면 인덱스를 사용하십시오.
AE

1
@DocBrown 테이블을 디자인 할 때 테이블 사용법을 이해해야합니다. 개인 테이블은 ID 또는 성으로 쿼리됩니다. 누군가가 DoB, 주소 또는 전화 번호를 통해 액세스하기 시작하면 모든 필드에 대해 색인을 추가하게됩니다.
gbjbaanb

4
@gbjbaanb : 사람들이 제품에 기능을 추가하는 것을 중단하면 끝납니다. 이는 방법론에 따라 "절대"일 수 있습니다.
Steve Jessop

1
@SteveJessop 액세스하려는 기본 열에 따라 색인을 생성한다는 의미입니다. 개인 테이블의 경우 검색 기능이있을 수 있지만 (예를 들어 사용자 이름을 잊어 버린 경우 이메일에서 검색 할 수 있음) 나중에 ID를 사용합니다. 따라서 ID는 색인이 필요한 유일한 것입니다. 다른 필드에서 많은 검색을 수행하면 색인이 필요할 수 있지만 시간이 지남에 따라 누군가가 비표준 쿼리를 작성하기로 결정했기 때문에 모든 열을 색인화하지는 않지만 일반적으로 모든 열을 색인화하지는 않지만 이러한 "일회용"사례에 대해 다른 메커니즘을 사용하십시오.
gbjbaanb

2
@gbjbaanb : 물론, 사람들은 테이블의 올바른 키보다 보유하기가 훨씬 더 편리한 손잡이이기 때문에 테이블에서 동일한 성을 반복해서 조회해서는 안됩니다 . 사실 테이블이 성을 기준으로 색인을 생성했는지 아닌지에 대해 말하고 싶습니다. 사실 "동일한 사용자"에서 작동하지만이를 표현할 수는 없다고 가정하는 코드 확장에 대해 비린내가 많기 때문입니다. ID를 기억함으로써 코드에서 :-) 나는 클라이언트가 그것을 언급 할 때까지 리버스 룩업이 필요하지 않은 경우를 상상하고 있었다 ...
Steve Jessop

26

"초기 최적화"란 그 의미 상 필요하지 않은 값 비싼 최적화를 의미합니다. 그것이 파산을 막기 위해 가능한 한 최신 포인트 이전에 모든 최적화가 구현 된 것은 아닙니다 !

특히, 앱이 완전히 빨리 지 않는 대략적인 요구 사항을 충족 할 수 있도록 라이브 전에 성능 테스트를 기반으로 최적화하는 것이 합법적입니다.

최소한 최소한 의 테스트 데이터로 데이터베이스를로드하고 앱의 응답 성을 확인해야합니다. 이것은 일어날 일을 알고 있기 때문에 너무 조잡하지 않으며 스캔을 느리게 트리거하는 쿼리를 잡을 것입니다. AE가 의견에서 말한 것처럼 :

최종 사용자가 일반적으로 실시간으로 수행하는 쿼리에 대한 전체 테이블 스캔을 피하려면 인덱스를 사용하십시오.

최소한 사용이 증가 할 계획 인 테이블의 경우.

데이터베이스 엔진에 대한 경험이 많고 코드의 첫 컷을 작성할 때 이미 테스트를 계획 한 경우에는 쿼리를 실행하지 않고도 알 수 있습니다. 색인이 없으면 쓰기 속도가 너무 느립니다. 물론, 당신은 당신이 모르는 척하고, 인덱스를 추가하기 전에 테스트가 실패하는 것을 지켜 볼 수는 있지만, 잘못된 코드 (응답하지 않기 때문에)가 생길 이유는 없습니다.


20

우리 응용 프로그램이 아직 출시되지 않았기 때문에 이것이 조기 최적화라고 생각합니다. 나는 우리가 라이브에 들어간 후 느린 쿼리를 모니터링하고 그에 따라 인덱스를 추가 할 것을 제안했습니다.

최종 사용자와 프로덕션 환경을 품질 보증처럼 취급 할 수 없습니다. 다시 말해, 프로덕션 환경에서 알아낼 것입니다. 나는 그것이 옳은 방법이라고 생각하지 않으며, 그 접근법은 매일 끔찍하게 잘못되는 것을 본다 .

넓은 브러시로 페인트를 칠할 수 없으므로 한 가지를 명심해야합니다.

일반적인 작업량 은 무엇입니까 ?

그것은 분명하거나 둔하게 들릴지 모르지만 실제로는 중요합니다. 작업 부하의 98 %를 구성하는 10 개의 쿼리가 있는 경우 (일반적으로 믿거 나 말거나) 프로덕션 전에는 권장 사항을 분석 하는 것이 좋습니다 . 현실적이고 대표적인 데이터를 사용하여 10 개의 쿼리가 가능한 한 우수해야합니다 ( 완벽한 것은 시간이 많이 걸리고 거의 달성 할 수없는 낭비입니다).

들어 작업 부하의 2 %를 구성하는 다른 200 개 쿼리 , 사람들은 대부분 노력의 톤 가치가 없으며, 생산 문제 해결 기이 반환 한 코너의 경우를 만들 것입니다. 그것은 또한 현실이며, 끔찍한 나쁜 것은 아닙니다. 그러나 이것이 인덱싱 모범 사례를 무시하거나 데이터 검색에 대한 추정 가정을 의미하는 것은 아닙니다.

프로덕션 전에 데이터베이스 성능을 파악하는 것이 일반적이며 좋은 방법입니다. 실제로, 개발 DBA 라는 이런 유형에 대해 비교적 일반적인 입장이 있습니다.

그러나...

어떤 사람들은 그것을 너무 멀리 가져 가서 "경우에 따라"색인을 추가하는 것에 열광합니다. 누군가 이것이 누락 된 색인을 권장합니까? 그것을 추가하고 다른 네 가지 변형을 추가하십시오. 또한 나쁜 생각입니다. 데이터 검색뿐만 아니라 데이터 수정은 어떻습니까? 테이블에 인덱스가 많을수록 일반적으로 데이터를 수정할 때 더 많은 오버 헤드가 발생합니다.

대부분의 것들과 마찬가지로 건전한 균형이 있습니다.

재미있는 작은 참고로 ... "인덱스"의 복수형

"지표"는 재정적 인 사람들을위한 것입니다

"인덱스"는 우리를위한 것입니다


2
투표가 더 필요합니다. 더 동의 할 수 없었습니다.
RubberDuck

은 "단지의 경우에"비트 +1 (즉 것이다 조기 최적화 수). 가능한 경우 "공통 워크로드"비트에 대해 다시 투표를했습니다.
David

바라건대 98 %에 속하는 10 개의 쿼리와 그렇지 않은 쿼리에 대해 미리 알고 있기를 바랍니다.
Paŭlo Ebermann

@ PaŭloEbermann 대부분의 DBMS에는 해당 정보를 매우 빠르고 쉽게 캡처 할 수있는 기능이 있습니다. 이 경우, 모르는 것에 대한 변명이 없습니다.
Thomas Stringer

@ThomasStringer 물론 프로덕션에 가기 전에 테스트 사례가 실제 사용자가 프로덕션에서 수행 한 작업과 관련이있는 경우에만 작동합니다.
Paŭlo Ebermann

4

아니요, 조기 최적화는 아니지만 최적화가 올바르게 수행되어야합니다.

여기 내가 할 일이 있습니다 :

  1. 프로덕션로드를 모방하기에 충분한 테스트 데이터로 데이터베이스를로드하십시오. 100 % 정확하지는 않지만 괜찮습니다. 충분한 데이터를 입력하십시오. 하나의 테이블에 고정 된 양의 데이터가 있습니까? 로드하십시오. 많은 양의 데이터를 보유한 하나의 테이블이 있습니까? 예를 들어이 사이트에서 질문이있는 테이블이 있습니까? 더미 데이터 일지라도 수백만 개의 레코드를로드하십시오.
  2. 데이터베이스 서버 에서 프로파일 링켜십시오 .
  3. 자동화 된 스크립트 (볼륨 제공)와 실제 사용자 (문제를 해결하는 방법)의 조합을 사용하여 응용 프로그램에서 벗어나십시오.
  4. 프로파일 링 데이터를 검토하십시오. 특정 검색어가 느립니까? 계획을 설명하고 데이터베이스 서버가 당신을 말하고 있는지 확인 하고자 인덱스를하지만 존재하지 않습니다.

데이터베이스 서버는 복잡하고 지능적인 소프트웨어입니다. 듣는 방법을 알고 있으면 최적화 방법을 알려줄 수 있습니다.

핵심은 최적화 전후의 성능 을 측정 하고 데이터베이스가 필요한 것을 알려주는 것 입니다.


3

알려진 문제에 대해 입증 된 패턴을 따르는 것 (예 : ID로 레코드를 찾는 것)은 아직 이른 것이 아닙니다. 그저 합리적입니다.

즉, 인덱스가 항상 간단한 비즈니스는 아닙니다. 트래픽이 의존하는 인덱스와 쓰기 작업의 병목 현상을 디자인 단계에서 파악하기가 어려운 경우가 많습니다. 그래서 저는 "명백한"스키마 설계 모범 사례를 활용한다고 주장합니다 (설계된 읽기 / 쓰기 패턴 및 색인 FK에 적합한 PK 사용). 그러나 스트레스 테스트가 요구할 때까지 다른 것에 인덱스를 두지 마십시오.


성능을 향상시키기 위해 거의 확실한 작업을 수행하기 위해 30 초를 더 소비하고 손상을 입지 않을 가능성은 "조기 최적화"가 아닙니다. 테이블에서 작업의 90 %가 특정 열을 키로 사용하는 경우 인덱싱을 수행하면 성능이 향상되거나 성능이 느려질 수 없으며 인덱스를 만들기위한 코드를 추가하여 시간을 절약 할 수 있습니다. 정말 필요합니다.
supercat

@supercat "never"... 프로덕션 환경에서 교착 상태가 나타날 때까지 ...
svidgen

열을 키로 사용하여 작업의 90 %와 일치하고 인덱스를 추가하면 교착 상태가 발생하는 실제 시나리오는 무엇입니까?
supercat

@supercat 나는 당신의 탐구를 완전히 이해하지 못합니다. 활성 응용 프로그램과 관련하여 실행 시간이나 iOS 수의 거의 모든 증가로 교착 상태가 발생할 가능성이 있습니다. 그러나 데이터베이스가 중요한 크기 및 / 또는 동시성 수준에 도달 할 때까지 대부분의 응용 프로그램 에서 인덱스의 존재 여부 는 무시할 수 있습니다. 예를 들어, 모든 인덱스가 더 이상 메모리에 맞지 않을 때 ...
svidgen

1
요점은 일반적인 사용 사례가 스트레스 테스트를 수행 할 때까지 (또는 프로덕션 환경에서 예기치 않은 사용자 동작에 문제가있을 때까지) 쿼리 구성이 무엇인지 아는 것이 어렵다는 것입니다. tablex.fieldy에서 키가있는 페이지가 있지만 1,000 번 삽입 할 때마다 한 번만 히트되는 경우 ... 색인의 순 성능이 저하 될 수 있습니다.
svidgen 2019

2

응용 프로그램이 릴리스되면 너무 늦습니다.

그러나 적절한 개발 프로세스에는 성능 테스트가 포함되어야합니다.

성능 테스트 결과를 사용하여 추가 할 인덱스를 결정하고 성능 테스트를 반복하여 효과를 검증하십시오.


응용 프로그램이 출시되면 실제로 인덱스를 조정하기에 좋은시기입니다. 이 사이트, stachexchange를보십시오. 당신은 당신의 모자가 시작한 후 오랜 시간이 바뀐 것을 내기 할 수 있습니다.
LosManos

@LosManos : 아무도 Stack Exchange를 사용하지 않습니다.
궤도에서 가벼움 경주

@LightnessRacesinOrbit : 반대로 광고주는 스택 교환을 사용하기 위해 비용을 지불합니다.

@JonofAllTrades : 인덱스 누락으로 인해 몇 시간 동안 성능이 좋지 않은 경우에는 신경 쓰지 않습니다. 필자의 요점은 영구 배포주기가있는 대규모의 무료 커뮤니티 중심 웹 사이트는 주기적으로 출시되고 자체 포함 된 상용 제품과는 매우 다르다는 것입니다. 따라서 SE는 좋은 예가 아닙니다.
궤도에서 가벼움 레이스

1

모든 쿼리를 최적화해야한다고 생각하지는 않지만 인덱스는 RDBMS의 일부이므로 릴리스하기 전에 고려해야합니다. 쿼리를 실행할 때 다른 형태의 프로그래밍과 달리 시스템에 쿼리 실행 방법을 알려주지 않습니다. 그들은 자체 계획을 개발하고 거의 항상 인덱스 가용성에 기초합니다. 데이터의 구성 및 볼륨도 나중에 고려 될 것입니다.

다음은 내가 고려해야 할 사항입니다.

  1. 초기 개발에서 자주 사용된다는 것을 알고있는 몇 가지 쿼리가 있습니다. 그들에게 집중하십시오.
  2. 쿼리 속도가 느려집니다. 먼저 색인을 생성하여 성능이 여전히 빠르지 않은지 판단한 다음 재 설계를 고려할 수 있습니다 (비정규 화가 조기에 발생할 수 있음). 릴리스 전에이 작업을 수행하고 싶습니다. 아무도 인벤토리에서 무언가를 찾는 데 10 분이 걸리는 시스템을 원하지 않습니다.
  3. 인덱스는 쿼리 성능을 향상시킬 수 있지만 데이터 수정을 방해하지는 않습니다.
  4. 많은 시스템에는 쿼리를 분석 할 수있는 도구가 있으므로 사용하는 것을 두려워하지 마십시오.

초기 검토 후,이를 다시 검토해야 할시기와이를 수행하기위한 정보 수집 방법 (모니터 사용량, 클라이언트 데이터 사본 가져 오기 등)에 대한 몇 가지 고려 사항을 따라야합니다.

조기 최적화를 원하지는 않지만 데이터베이스를 색인화하지 않으면 성능이 저하 될 것이라고 확신합니다. 이를 방해하여 성능 문제를 일으키는 다른 영역이 있는지 확인할 수 있습니다.


0

또한 예상되는 사용자 수에 따라 다릅니다. 로드 테스트를 확실히 수행하고 데이터베이스가 10에서 100에서 1000의 동시 요청을 유지할 수 있는지 확인해야합니다. 다시 말하지만 예상 트래픽 양과 다른 영역보다 더 많이 사용될 것으로 예상되는 영역에 따라 다릅니다.

일반적으로 사용자가 가장 먼저 칠 것으로 예상되는 영역을 미세 조정합니다. 그런 다음 사용자 경험의 관점에서 느린 것을 미세 조정합니다. 사용자가 무언가를 기다려야 할 때마다 나쁜 경험을하게되고 거절 될 수 있습니다. 안좋다!


0

사전 분석을 통해 인덱스가 필요한 열을 식별하는 것이 좋습니다. 인덱스가 전혀 없으면 데이터베이스 크기가 증가함에 따라 프로덕션에서 점진적이거나 예기치 않은 성능 저하가 발생할 위험이 있습니다. 피하고자하는 상황은 일반적으로 실행되는 쿼리가 많은 수의 테이블 행을 스캔해야하는 경우입니다. 사용 가능한 필수 정보가 많고 잠재적 인 성능 차이가 중요하기 때문에 (주문 수) 중요 열에 인덱스를 추가하는 것은 조기 최적화가 아닙니다. 지수의 이점이 데이터에 덜 명확하거나 더 의존하는 상황도 있습니다. 이러한 경우 중 일부에 대한 결정을 연기 할 수 있습니다.

몇 가지 질문이 있습니다 :

  • 각 테이블의 크기에 대한 디자인 제한은 무엇입니까?

테이블이 항상 작을 경우 (예 : <100 개 행) 데이터베이스가 전체 테이블을 스캔해야하더라도 재앙이 아닙니다. 인덱스를 추가하는 것이 도움이 될 수 있지만이를 확인하려면 약간의 전문 지식이나 측정이 필요합니다.

  • 각 쿼리는 얼마나 자주 실행되며 필요한 응답 시간은 얼마입니까?

쿼리가 자주 실행되지 않고 엄격한 응답 시간 요구 사항 (예 : 보고서 생성)이없고 행 수가 많지 않은 경우 인덱스 추가를 연기하는 것이 상당히 안전합니다. 다시 한 번 말하지만, 전문 지식이나 측정이 도움이 될 것인지 판단하는 데 도움이 될 수 있습니다.

  • 쿼리에서 기본 키 이외의 다른 방법으로 테이블을 조회해야합니까? 예를 들어, 외래 키에 참여하여 기간별로 필터링 하시겠습니까?

이러한 쿼리가 자주 실행되고 행이 많은 테이블을 만지면 인덱스를 사전에 추가하는 것을 진지하게 고려해야합니다. 이것이 쿼리에 해당되는지 확실하지 않은 경우 데이터베이스에 실제 데이터를 채우고 쿼리 계획을 살펴볼 수 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.