안녕하세요.
INDEX 함수로 검색하는 방법이 아주 빠르다고 해서 애용중입니다.
아래는 이 공식에 대한 실제의 예입니다.
=INDEX(A:A, 3)
A열 전체 범위(A:A)에서 3번째 행에 있는 값을 가져옵니다그런데 위보다 더 빠르게 할려면
A:A 처럼 하지 말고 A1:A9999 처럼 명확하게 범위를 지정하라고 인공지능이 대답해 주었습니다.
인공지능에게 엑셀 최대행 갯수는? 이라고 질문하면 아래와 같이 대답해줍니다.
엑셀에서 최대 행 갯수는?
최대 행 수: 1,048,576개 입니다. 이 말인 즉슨
=INDEX(A:A, 3) ---> 1,048,576번 검사한 후에 , 3번째 찾음.
=INDEX(A1:A9999, 3) ---> A1:A9999 이므로 9999번 검사한 후에 3번째 찾음.
즉, 이런 논리라면 위 중에 무엇이 속도가 더 빠른 지는 금방 알 수 있겠네요. 후자가 더 빠르겠죠.제 이해가 맞는지 아닌지는 모르겠지만, 이는 제가 질문할 사항이 아닙니다. 단지...
제 질문을 여러분들께 명확하게 이해시켜드릴려고(최대한 성의있게 질문드릴려고) 전채처럼 먼저 내온 음식같은 것이구요.
이제 드디어 질문드립니다.

질문예제파일에 있는 기능은 위와 같이
=INDEX(Sheet1!A$1:Sheet1!A$9999,A$1-1)
시트1 에 있는 1행~9999행 중에서 마지막 1 개행의 값을 가져오시오이구요. 이것이 10개가 있으니 최정적으로 10개 행을 가져옵니다.
그 셀들이 하는 일을 도식화하여 설명드리면
1 ~ 9999 번째 행 중에서 마지막 10번째
.
.
.
1 ~ 9999 번째 행 중에서 마지막 3번째
1 ~ 9999 번째 행 중에서 마지막 2번째
1 ~ 9999 번째 행 중에서 마지막 1번째.....와 같습니다. 그런데 각 셀들은 저마다...
1 ~ 9999 번째 행 중에서 ........ 이 동일계산을 각각 셀마다 반복하고 있습니다. 고정된 것인데도요. 그러면 그러면 효율적이지 않잖아요.
윗행도 아랫행도 10개 행 모두가 [ 1 ~ 9999 번째 행 ] 을 검사하고 마지막 몇번째. 이런 식으로 [ 1 ~ 9999 번째 행 ] 이라는 과정이 고정되어 있어요.
그 부분이 바로 아래 문구에 해당될 테구요.
=INDEX(Sheet1!A$1 : Sheet1!A$9999, A$1-1 ) <-- 원래 수식. 이런 수식이 10개 있음.
Sheet1!A$1 : Sheet1!A$9999 <--- 위 수식중 쓸데없이 반복중인 부분. 이 파일에서는 10번 반복중. 위 [ 쓸데없이 반복중인 부분 ] 을 [ 하나의 고정값 ] 으로 치환해버리고 싶습니다.
이 파일에서는 어차피 10개의 행 모두가 [ 동일한 계산 ] 에 해당하잖아요. 동일하므로 1번만 하면 되는데 각 10개가 각자 하고 있으니 불필요한 행위라는거죠.
그런데 문제는 [ 고정해야할 것 ] 이 [ 값이 아니라 범위] 라는 것이 문제입니다. 고정값 말고, 고정범위를 치환하는 방법을 모르겠습니다.
만약, 이게 숫자로 된 값이라면 ... 예를 들어 그 값이 32344 라는 특정 숫자라면
[ 쓸데없이 반복중인 부분 ] - 이걸 C1 에 저장 하면
=INDEX(Sheet1!A$1 : Sheet1!A$9999, A$1-1 ) <-- 원래 수식
Sheet1!A$1 : Sheet1!A$9999 <--- 쓸데없이 반복중인 부분
C1 <--- 고정값으로 치환, C1 = 32344 라면
=INDEX( C1, A$1-1 ) <-- 최종
= INDEX( 32344 , A$1-1 ) <-- 최종 ( 드디어 행 카운트 하지 않게 됨. 32344 번째 행. 고정됐으니까)이렇게 되면 각각 셀들은 힘들게 [ 쓸데없이 반복중인 부분] 계산할 필요없게 되잖아요.
= INDEX( 32344 , A$1-1 )
위 셀수식을 엑셀이 해석/행동하는 입장에서 TV축구중계의 느린화면(슬로우모션) 처럼 자세히 살펴보면...
이 셀에 도착해서 할일이 무엇인가 살펴보니...
1. 이것은 셀에 = 이 있으므로 함수이다. 그리고 INDEX다. 그러면 INDEX 문법이 약속한대로 진행하면 되겟네.
2. INDEX 의 첫째문구는 범위이다. 그 범위는 32344 부터 32344까지이다. 그러므로 1개만 있는 범위이므로 카운트고 뭐고 없이 그냥 32344 를 쳐다보기만 하고..
3. 그 다음동작으로 넘어간다. 그 다음 동작은 범위 다음에 쉼표 , 가 오고 이때부터 [ A$1-1 번째라는 것을 가져오는 것 ] 으로 해석한다. 그래서 A$1에 입력된 숫자에서 1을 빼면 [어떤 숫자] 가 나온다. 결국 내가 할 일은...
4. 32344 부터 32344까지 범위에서 그 [어떤숫자번 ] 째의 값을 이 셀에 반환한다.
5. 이상 이 셀에서 내 할일은 마쳤다. 이제 다음 셀로 넘어간다.
.. .입니다.
위에서 INDEX라는 함수를 가장 시간잡아먹게 하는 곳이 범위를 카운트하는 위 2 의 과정이라고 생각합니다. 그런데 [ 32344 부터 32344까지 ] 라고 해주면 계산이고 말것도 없이 고정시켜 줘버리면 속도가 빨라지겟네요.
덧셈이고 뺄셈이고 연산이 아예 없고 범위를 카운트할 것도 없잖아요.이런 식으로 치환하고 싶습니다. 그런데 고정값(Value)이 아닌 고정범위(Range)는 어떻게 치환하나요? 제 질문이 바로 이겁니다.
질문 요약 :
숫자처럼 고정된 값(Value)이면 특정셀(C1)에 넣고 C1 의 값을 참조하는 방식으로 치환시키면 효율적인데(아주 간단한데), 저렇게 값이 아니라, 범위(A1:A9999) 가 고정된 경우 어떻게 치환시킬 수 잇나요? 이게 가능하면 각 셀들은 A1~A9999 까지 9999번 카운트하지 않아도 되잖아요. 고정됏으니까요. 그러면 서두에 인공지능이 밝힌 바와 같이 행갯수를 카운트 하지 않아 결국 INDEX 속도향상을 꾀할 수 있잖아요. 만약 이런 셀이 10개 정도면 문제없다행도 1백만개 있다면 이는 큰 이슈가 되겠죠.
질문 1 : 그래서 이런 범위(Range)를 어떻게 고정으로 치환시킬 수 있는 지 질문드립니다. 엑셀은 너무 똑똑해서 분명히 이런 장치를 마련해놓았을텐데요.
질문 2 : 그런 장치가 없다해도, 그런 장치에 버금가는 엑셀-테크닉적인 방법이 있을까요? ( 유사한 예: 문자열 "12345"를 숫자화시키는 건 함수를 몰라도 된다. 설령 그런 함수가 있다해도 우리는 테크닉적으로 "12345" * 1 을 곱해주어 숫자화시키는기술을 구사할 수 있다. 이런 건 엑셀교재에 나오지는 않지만 너무 흔하게 사용하는 주요테크닉이다. )
감사합니다.
안녕하세요~
오늘도 퍼포먼스에 대한 고민으로
질문을 주셨네요.
간단히 정리하자면,
INDEX(A1:A9999, ...) 수식이 10번 반복될 때, 엑셀이 A1:A9999라는 범위를 10번 모두 "새롭게 인식하고 계산"하는 비효율이 발생한다고 판단하셨고
이에 따라 반복되는 범위(A1:A9999)를 마치 "변수(Variable)"처럼 하나의 고정된 객체(예: C1 같은 특정 공간)에 담아두어 각 수식이 범위를 매번 새로 읽는 것이 아니라, 이미 정의된 객체를 "참조(Reference)"만 함으로써 계산 속도를 높이고자 합니다.
먼저 성능에 대한 오해를 바로 잡을 필요가 있는 듯 합니다.
질문자님 설명 중 아래 부분,
이것은 일반적인 오해이며 실제 동작은 다르게 하는데,
스캔(Scan)이 아니라 Direct Access(직접 인덱싱) 방식으로
즉,
이라고 했을 때 엑셀은
A1부터 A5000까지 차례로 탐색하지 않고 바로 A5000 셀 주소로 점프합니다.
(프로그램 언어에서 배열의 인덱스로 접근하듯이)
따라서
INDEX 자체는 범위 크기로 인해 느려지지 않지만 범위를 A:A처럼 너무 크게 잡으면 전체 계산 체인이 커져서
엑셀의 “종속성 트리(dependency tree)” 분석이 느려지는 것입니다,
즉,
INDEX 자체는 엑셀에서 가장 빠른 함수 중의 하나이긴 하지만 "너무 큰 범위"는 전체 파일 재계산을 느리게 하기 때문에 범위를 좁히면 성능이 좋아지는 것입니다.
이 점을 명확히 이해해야 최적화가 올바르게 이루어진다고 볼 수 있습니다.
질문으로 돌아와서,
1. 질문에 대한 고전적인 해결책은
"이름 정의" 기능으로 정확히 범위를 변수처럼 저장하는 방식입니다.
이름 정의는 엑셀 엔진 레벨에서 메모리 주소를 매핑해 놓은 것으로 고정범위일 경우 함수 파싱 없이 바로 주소를 쏘기 때문에 오버헤드가 '0'에 가까워 대단히 빠르지만, 범위가 FILTER 수식 등에 의해 동적으로 변할 때는 약간의 오버헤드가 발생할 수 있습니다.
Sheet1의 A1:A9999 범위를 드래그하여 선택하고
이름 상자를 클릭하여 원하는 이름(예: MyData)을 입력하고 Enter를 칩니다.
셀에는
이렇게 변경합니다.
그러면 이제 엑셀은 MyData라는 이름을 보자마자
A1:A9999라는 메모리 주소를 즉시 찾아가는 "범위를 고정값처럼 치환"합니다.
즉, 엑셀은 “이름정의 범위”를 재사용 캐싱 처리하므로
별도로 10개 셀에서 각각 “A1~A9999”를 새로 계산하지 않게 됩니다.
2. 최근 버전의 엑셀에서는 LET함수를 사용하면
질문자님께서 기대하시는 효과를 얻으실 수 있습니다.
여기서 r 변수는 한 번만 평가되어 여러 번 사용해도 재계산이 일어나지 않고,
셀 내부에서 범위를 변수처럼 다룰 수 있어 매우 빠르고 최적화되어 있습니다.
3. 결론적으로,
단일 셀 내부에서의 순수 계산 속도만 비교하면
Inline 방식의 LET이 가장 빠르다고 볼 수 있습니다.
이름정의(Named Range)는 "고정 범위(static range)"를 참조할 때에는
실질적으로 LET과의 속도 차이가 거의 없지만,
내부에 FILTER, SORT, UNIQUE 등 동적 범위(dynamic array) 수식이 포함되어 있을 경우에는
해석 과정에서 한 번 더 참조 단계를 거치기 때문에
아주 미세한 오버헤드가 발생할 수 있습니다.
다만 이러한 차이는 대부분의 실무 환경에서는 체감하기 어려우며,
수식이 매우 크거나(수천~수만 셀), 대량 데이터(10만 행 이상)를 처리하는 상황에서는
LET의 캐싱 효과가 더 확실히 유리하게 작용합니다.
다만 이러한 접근은 연산 속도만 보는 단편적인 관점으로
유지 보수 관리 측면에서는 또 다른 관점으로 접근해야 할 필요는 분명히 있습니다.
여러 다양한 관점을
참고삼아 활용해 보시면 좋을 듯 합니다.
수메리안 선생님 안녕하세요. 날씨가 추워졌는데 강녕하셨습니까?
네. 맞습니다. 제 질문을 정확히 요약해주셨네요. 제가 이런 생각을 하게된 이유는 그동안 시트 여기저기 위치한 값들 중에서 참조할 값들을 어떻게 빨리 찾을수 있을까 궁리하다가 vlookup, counta 등 여럿을 시도해봤는데 그중 가장 나은 것이 INDEX/Match 라는 결론을 냈습니다. 속도체감을 딱히 느끼지는 못하지만 엄청난 대용량일때에는 그나마 가볍고 빠른것 같아요. 그런데 INDEX 수식을 자주 사용하다가 참조횟수가 늘면서 =INDEX(A:A, 3) 도 부하가 걸리니 결국 =INDEX(A1:A9999, 3) 와 같이 범위를 지정해주어 속도향상을 꾀할 수 있다는 힌트를 인공지능으로부터 얻었습니다. 값이 어디 있는 지 명확한 구역 범위로 제한되어 있다면 충분히 이렇게 개선하는 것이 맞을 겁니다. 인공지능이 알려준 첫째 전략으로 나오는 것은 [ 참조범위를 최소화하여 불필요계산을 줄인다 ] 인데요. 아래와 같았습니다.
위와 같이 대답하니 제 결론은 =INDEX(A:A, 3) 라면 먼저 이 함수는 A:A 를 카운트한다는 오해(?) 를 했던 것 같습니다. =INDEX(A1:A9999, 3) 라면 카운트 횟수가 줄어드니 빨라진 결과를 낳게 되구요. 이 둘의 차이는 이것 외에는 없으니 속도차이는 당연히 이 카운트횟수에서 기인한다는 결론을 내게된 건데요. 지금 생각해보니 제가 제대로된 헛발질만 하고 있었다는 것을 실감하네요. 선생님 설명을 듣고보니 INDEX 는 배열로 바로 그 번호로 점프하는 방식을 사용하고 있었다니 아~ ㅠ 제가 머리가 띵해지네요. INDEX를 직관적으로 따지지않고 너무 심도있게 궁리한 것이 아닌가 지금와보니 후회가 듭니다.
직관적으로 생각해도 INDEX가 이렇게 무식하게(전체를 카운트한다는게 좀 무식하잖아요) 만들어졌을 리가 없을텐데 왜 인공지능은 저런 대답을 할까? 였구요. 그런데 저는 내심...이럼에도 불구하고 참 엑셀이 빠르기도 빠르네~ 감탄스럽기도 하고 1,048,576번째 행까지 검사하는 것이 만만치 않을텐데 어찌 이리도 빠를까? 이게 [ 셀수식은 인터프리터 방식이 아니고 완전 컴파일화 수행되어 com 과 직접 통신하는 방식의 위대함인가? 사실상의 속도 = 0 에 수렴된 극한의 속도향상이라고도 생각하기도 했었습니다. 그런데 이런 셀수식이 100만개가 있다면 만만치 않을텐데~ 어떻게 순식간에 계산이 될까? 라는 의심도 있었습니다.
인공지능이 이런 설명을 해줬어야 했는데, 원리를 가르치지 않고 곁가지 정보로 결론만 알려주니 제가 여기까지 잘못 인도된것 같네요.
먼저 선생님께서 제시해주신 방법을 시도해 봤습니다.
아~ 역시 이 방법이 있었군요. MyData 의 정의는 딱 1번만 하고, 셀수식에서 필요할 때마다 불러주기만 하면 되니까요. 네. 제가 원했었던 방식입니다. 범위를 이름으로 정의하는 방식은 익이 들었는데 왜 이걸 생각하지 못했을까? 약방에 감초가 넘쳐나도 정작 제가 아플 땐 그 약초를 달여먹을 생각은 못하고 혼자 끙끙 앓던 바보였네요.
그런데 위 방식은 좀 의문이 듭니다. 저는 선생님의 설명을 듣고 [ C1 셀수식에서 저렇게 r 을 LET 으로 1번 정의해주면 다른 셀 A2 에서는 그냥 r 만 불러주면 되는건가? LET 없이도.. ] 라는 생각이 문득 들었습니다. VBA 전역변수처럼 셀수식에서도 이쪽저쪽 전역화된 방식이 도입된건가? LET이라는 함수를 알아보니 엑셀365버전부터 생긴 최신기법이라고 나와있더라구요. 그래서 제가
... 이라고 하니 첫번째 수식은 잘 계산이 되고 2번째부터는 수식이 그냥 셀에 보여지네요. 계산값이 보이지 않아요.
선생님께서도 한번만 평가되어 재계산이 일어나지 않는다고 말씀하셨는 어찌된 일일까요. 여기 오빠두에 올려진 예제파일도 살펴보았습니다.
근데 이렇게 하면 계산값이 잘 보여지긴 합니다. 그런데 이렇게하면 LET 정의를 10번 한다는 건데요. 이러면 결국 또 느려지지 않나요? 이건 [ Sheet1!A$1:Sheet1!A$9999 라는 반복동작을 줄여 속도향상을 꾀한다는 전략을 세울려고 했었는데, 그걸 반복하지 않지만, LET(r,Sheet1!A$1:Sheet1!A$9999, ... 라는 새로운 반복동작 ] 이 생겨버렸잖아요. LET 정의를 셀마다 1번씩 총 10번하게 되잖아요. 만약 이걸 A1셀에서 1번만 수행하고 다른 셀에서는 수행할 필요없다면 좋을텐데요. 이런 셀이 100만개 있는 파일에서는 엄청난 속도향상이 생길텐데요. 제 이해가 맞나요?
선생님께서 더불어 알려주신 LAMBDA 는 좀더 공부를 해야할 것 같습니다. 어쨌든 선생님의 친절하신 설명에 고개숙여 감사드립니다. 좋은 밤 되세요.
예,
그렇게 궁금해 하시는 게 맞습니다.
LET은 셀마다 독립적으로 실행되기 때문에
"r 정의"를 셀마다 1번씩, 총 10번 수행합니다.
즉,
LET은 "범위 평가를 파일 전체에서 딱 1번 처리하여 전역 캐싱하는 기능"은 없습니다.
그래서
위 답변 중에
라고 말씀드린 부분이 LET은 "지역 변수(Local Variable)"라는 정의입니다.
질문자님이 생각하시는
"범위를 1번만 정의하고 모든 셀에서 재사용하고 싶다"는 부분은 전역변수(Global Object)로 처음에 언급했던 이름정의(Named Range)의 역할입니다.
그래서
LET은 "지역 변수(Local Variable)"이고 이름정의(Named Range)는 전역변수(Global Object)로 두 개의 역할이 완전히 다릅니다.
LET은
그 셀 안에서만 유효하고, 셀이 계산될 때마다 해당 LET 블록을 다시 평가하므로
LET으로 만든 r은 범위 자체가 캐싱되는 것이 아니라, 수식 내부의 연산이 캐싱되는 것입니다.
즉,
이러할 때,
셀1의 r과 셀2의 r은 아무 관계가 없고
전역 캐싱은 일어나지 않습니다.
그래서 질문자님이
"이러면 반복 범위 해석을 줄이려는 전략을 세웠는데 오히려 LET이 10번 반복되잖아요?”
말씀하신 부분이 맞는 것입니다.
LET은 "그 셀 내부의 중복 계산 제거용"이지,
"여러 셀이 공통으로 사용하는 범위를 1번만 평가하게 하는 장치"가 아닙니다.
LET은,
이 무거운 수식을,
이렇게 적용할 때, 비할 데 없이 빠릅니다.
즉, LET은 수식 내부 최적화입니다.
하지만 여러 셀에 걸쳐 범위를 “전역 캐싱”하는 기능은 없습니다.
그래서 위 댓글이 마지막에 권해드린,
전역변수 이름정의를 활용한,
이러한
수식구조를 권해드린 것입니다.
아~ 네 감사드립니다. 제가 미처 ....
이라는 말씀을 살펴보지 못했었네요. 모르니 무엇이 중요한 지도 모르는 제자신이 참 답답합니다. 배워야할 것이 아직도 많은데.. 또 한보따리를 짊어지고 온 느낌입니다. 엑셀을 겉으로 아는 것과 내적으로 아는 것. 이 둘은 하늘과 땅 차이라는 것을 실감합니다. 엑셀을 대충 하는 건 쉬워도 잘하는 건 정말 만만치 않은것 같네요. 일단 범위를 사용자이름 정의로 방향을 잡아 속도개선을 시도해보겠습니다. 질문을 드릴 때마다 매번 친절하고 자세히 알려주셔서 감사드립니다. 용어 하나라도 소중히 알고 새겨듣고 있습니다. 다음에 또 찾아뵙겠습니다. 좋은 주말 보내세요.
질문들을 보면 거의 대부분이 퍼포먼스에 대한 고민이시네요.
일반적인 현업 개발자 같지 않다는 생각이 듭니다.
보통 개발을 하려면 기본 기능을 완성시켜놓고 전체적으로 무난하게 돌면 완료입니다
5~10% 정도의 효율 개선을 위한 고민은 잘 안하죠.
개발 리소스 투입대비 효율성이 많이 떨어지기 때문입니다
안녕하세요. 네. 저는 개발자가 아닙니다. 저는 은퇴해서 놀다가 1년 전에 조그만 부업일을 시작했는데요. 일을 하다보니, 이런 작업은 탁상용 계산기를 두드리는 것보다 엑셀이라는 걸 두드리면 좀더 나을 것 같다는 생각이 들어 어찌저찌 공부를 시작하게 되어 여기까지 오게된 것 같습니다. 엑셀을 알아가면 알아갈 수록 퍼즐조각을 맞추는 것처럼 재미를 느끼니 아마 이런 기분은 우리 선조님들이 이미 간파하셨던, 배우고 때때로 익히는 재미를 알면 이 또한 기쁘지않을 수 없다는 것을 경험하게 됩니다. 그러나 지식이 일천하여 여러 선배님들에게 조언을 구하려 여기저기를 기웃거리고 있습니다. 심봉사가 앞을 못보더라도 심청이를 안고 알음알음 이웃들에게 길을 물어 젖동냥을 떠나는 심정으로 물어봅니다. 너그럽게 이해해주시면 감사드리겠습니다.
질문이 너무 길어서 자세히 읽어보진 않았지만..
index함수에 A:A열 전체를 잡는것과 A1:A9999와 같이 범위를 잡는것은 속도의 차이가 없습니다.
index 함수는 행과 열번호에 의해서 해당 참조나 배열에 값을 가져오는데 말 그대로 해당 index 번호에 접근하여 바로 가져오는겁니다. 특별히 검색하거나 내부 알고리즘이 있는게 아닙니다.
보통은 열 전체를 참조로 잡는 방식이 함수의 연산 속도를 크게 떨어뜨리는게 맞습니다. 단 INDEX와 COUNTIF(S), SUMIF(S)와 같은 조건부 집계함수는 아닙니다.
이 둘은 틀린데.. INDEX는 해당 열, 행번호에 바로 접근하여 결과를 가져오는 방식이므로 참조의 크기와는 무관합니다.
시험 삼아서 한번해보세요.
=INDEX(Sheet1!A:A, SEQUENCE(999999)),
=INDEX(Sheet1!A1:A999999, SEQUENCE(999999))
약간의 지연이 발생하는데 이 둘은 같습니다.
COUNTIF(S)와 같은 조건부 집계함수는 criteria_range를 참조만 받습니다. 이 참조를 받는 것은 A:A와 같이 열 전체가 인수로 들어와도 내부 엔진에서 자동으로 데이터의 처음과 끝을 인식하게끔 합니다.
2016버전 이후로 조회 함수에도 일부 이 기능이 도입되었다고 하는데 정확히 참조일때만 이 기능이 되는지는 저도 잘 모릅니다.
나머지 함수들은 A:A와 같은 열 전체 참조를 사용하게 되면 성능이 크게 떨어집니다. AI가 설명한 대로 열전체에 대해서 함수의 평가가 이루어집니다.
AI를 완전히 믿지마세요. 깊이 들어가면 오류 투성이입니다.
=LET(r,Sheet1!A$1:Sheet1!A$9999,INDEX(r,A$1-10))
=LET(r,Sheet1!A$1:Sheet1!A$9999,INDEX(r,A$1-9))
=LET(r,Sheet1!A$1:Sheet1!A$9999,INDEX(r,A$1-8))
=LET(r,Sheet1!A$1:Sheet1!A$9999,INDEX(r,A$1-7))
=LET(r,Sheet1!A$1:Sheet1!A$9999,INDEX(r,A$1-6))
=LET(r,Sheet1!A$1:Sheet1!A$9999,INDEX(r,A$1-5))
=LET(r,Sheet1!A$1:Sheet1!A$9999,INDEX(r,A$1-4))
=LET(r,Sheet1!A$1:Sheet1!A$9999,INDEX(r,A$1-3))
=LET(r,Sheet1!A$1:Sheet1!A$9999,INDEX(r,A$1-2))
=LET(r,Sheet1!A$1:Sheet1!A$9999,INDEX(r,A$1-1))
뭐 이런식으로 LET으로 참조를 잡고 수식 복사를 사용하시는것 같은데..
이런식으로 사용하는게 아닙니다.
엑셀 2024 버전을 사용하는 동적배열은 절대, 혼합 참조는 쓰지도 않고 수식 복사 방식도 쓰지 않습니다.
상대 참조로 분산 배열 방식을 사용합니다. 기존에 수식 복사방식과 완전히 다른개념입니다.
이런걸 물어보기 전에 동적배열에 기본 사용법부터 배우세요. 지금 순서가 잘못됐어요.
INDEX 함수에 따로 LET으로 참조를 변수화 시킬필요도 없고 그냥
=INDEX(Sheet1!A1:Sheet1!A9999, A1 - SEQUENC(10, , 10, -1))로 하면 됩니다.
INDEX 함수에 단독으로 사용하는 참조를 따로 r 변수로 둘 필요가 없어요. 만약 r 변수로 참조를 저장해 두는것은 성능 향상을 위해서가 아니라 다른 함수에서도 이 참조를 쓸 일이 있다면 수식 작성의 용이성과 유지보수의 목적으로 변수화 하는 것이지 성능과는 전혀 무관합니다.
참조를 변수화 해서 재사용하는 것은 나중에 수식을 고치거나 할 일이 있을때 일일히 그 참조를 바꾸기 보다 변수화된 r 참조를 한번 바꾸면 되기 때문에 이런 관점에서 변수화 하는겁니다.
참조 자체는 평가가 아닙니다. 그냥 참조에요. 이걸 변수화해서 참조 자체를 평가한다?
참조는 평가하는게 아닙니다. 그냥 데이터에요.
항상 성능 테스트를 하시는것 같은데.. 성능 최적화는 코드나 함수에 사용을 충분히 할수 있고 난 다음에 하는겁니다.
내부 논리를 모르는데 하는 성능 최적화는 바로 한계에 직면합니다.
안녕하세요. 금과옥조와 같은 질타와 댓글에 먼저 고개숙여 감사드립니다.
제가 무엇을 우선해야 하고 어떤 순서로 문제해결을 해야할 지를 잘 알려주신 것 같습니다. 체계적으로 공부하지 못하고 문제가 생길 때마다 그것을 해결하는 방식은 부분에서 전체를 이해하려는 시도이니 이는 분명히 잘못되었다는 것을 저도 느끼고 있었습니다. 저도 이제서야 INDEX에 대해서 좀 알게 되었는데, 인공지능이 A:A열 보다는 A1:A9999 로 범위를 잡아야 수행속도가 더 빠르다고 대답헤주니, 저는 당연히 INDEX 구동원리 안에는 A열을 카운트하는 과정이 있을 것이라는 추측을 하게된 건데, 이는 잘못된 추측이고 여기서부터 방향이 틀어져버린 것 같습니다.
선생님 말씀처럼 A1:A9999 는 연산도 아니고, 논리식도 아니고, 함수안에 존재하는 내장(?)함수도 아니고, 쉽게 말해 시간잡아먹을 것이 없는, 그냥 참조 그 자체일 뿐인데, 인공지능은 왜 A:A 보다 A1:A9999 가 더 빠르다고 대답할까? 그에 대한 의문도 있었습니다. 선생님 말씀을 들어보니 INDEX 부류, COUNTIF 부류로 분리하여 따져야할 문제인 것 같습니다. 저는 선생님 설명을 듣고 이렇게 이해했는데 맞나요? Criteria Range 에 대한 용어도 찾아보니 제 이해가 맞는 것 같기도 하구요. COUNTIF 부류들은 A:A 일때는 전체 열을 검사하고, INDEX 부류는 A:A 라도 참조사이즈를 따지지 않는다로 이해했습니다. 그렇다면 결국 첫 원점으로 되돌아가야 할 것 같습니다. 궁리할 필요가 없는 것을 저는 궁리하고 있었다고 봐요. 범위지정 크기를 줄여 INDEX 속도향상을 꾀한다는 전제가 이미 잘못된 것 같아요. INDEX는 참조의 크기를 따지지 않고 배열로 바로 접근하는 방식을 쓰고 있다는 것을 이제 잘 알았습니다.
선생님께서 알려주신 상대참조, 분산배열방식, 동적배열 등에 개념을 명확하게 인식하고 공부해나가야할 것 같습니다. 참 좋은 말씀을 많이 해주신것 같은데 제가 아직 이쪽 지식이 부족하여 뭐라 대답해야할 지 잘 모르겠습니다. 노트에 적어놓아 꼭 나중에 학습하도록 하겠습니다. 제가 부족함이 많다는 걸 느낍니다. 따끔하게 편달해주셔서 감사드립니다. 좋은 주말 보내세요.
COUNTIF(A1:1A10, ">10) 이런 식이나
COUNTIF(A:A, ">10")나 성능에 차이가 없다는 겁니다.
대부분에 함수는 A:A 열 전체 1048576의 데이터를 모두 평가하나 COUNTIF는 인수로 A:A가 들어와도 첫번째 식처럼 내부적으로 A1:1A10으로 참조를 데이터가 있는 범위로 축소 변경하여 수식을 평가한다는 겁니다.
COUNTIF 쪽에서는 지연이 발생하지 않습니다.
SUMPRODUCT 쪽에서는 인식할수 있을 정도에 지연이 발생합니다.
자세한 부연설명을 해주셔서 감사드립니다. 셀수식의 퍼포먼스를 평가할 때에는 어떤 방법이 쓰여질까? 정말 궁금했었는데, 뜻하지 않게, 선생님이 쓰고 계신 방법을 보니, 정말 이런게 있었나 싶을 정도로 기발한 방법이 있었네요. 올려주신 짤을 유심히 살펴보고 있습니다.
VBA는 흔히 Timer 를 사용하여 평가하잖아요. 언젠가 제가 인공지능에게 물어본 건데 [ 셀수식의 속도를 측정하는 방법은 무엇인가? ] 라는 질문을 던졌던 적이 있었습니다. 그런데 답변은 [ 직접적인 방법은 없다 ] 였습니다. 그리고 [ 굳이 속도측정을 꼭 해야한다면 수식실행 전에 스톱워치를 누르고 종료후에 스톱워치를 눌러 시간을 잴 수 있다 ]라는 황당한 답변을 받은 적이 있습니다. 그런데 저렇게 (어떤 건지는 잘 모르지만) 측정을 하는 방법이 있었군요.
저 위쪽 댓글에서 알려주신 이 방법도 참 대단한 방법이라고 생각했었는데요. 이것도 예제파일을 만들어 직접 해볼려고 하거든요. 많은 정보를 주셔서 감사드립니다. 즐거운 주말 보내세요.
AI에 말을 확신하지마세요. 직접적인 방법은 없다?
위에 스샷은 그냥 간단히 보여준겁니다.
현재 동적배열과 LAMBDA는 더 이상 함수가 아닙니다. 프로그래밍 언어입니다.
LAMBDA를 사용하면 수식의 평가시간을 측정하는 함수를 만들수 있습니다.
그냥 평가하는 것도 아니고 100번 돌려서 평균을 낸다던가.. 표준편차를 측정한다건가..
제약 사항은 VBA와 마찬가지로 1/100초까지만 측정가능합니다. 이건 엑셀의 태생적 한계에요. 나노세컨드까지 측정하려면 vba 윈도우 api 사용해야 합니다. 하지만 그렇게까지 측정할 일이 없어요.
100 th: 0.000 [sec] 이라고 나온건 100번 돌려서 평균 밀리 세컨드로 측정할수 없을만큼 빠르기 때문에 0이라고 나온겁니다.
10 th: 0.798 [sec]은 10번 돌려서 평균 0.798초가 나온겁니다.
와~ 참. 세상은 넓고 고수님들은 여기저기 계시네요. 제가 엑셀 걸음마단계를 지금 막 벗어난 수준이라고 자부하는데 그나마 정보를 찾으려 먼길 마다않고 해외커뮤니티까지도 열람하고 있는데 우리 한국만큼 빠른 답변을 받는 곳은 없는것 같습니다. 심지어 정말 고수님들이 한두분이 아닌거 같아요. 저런 방법이 있었다는 것을 알았다면 제가 생고생을 하지 않았을텐데... 셀수식 속도측정하는 방법은 없다는 인공지능 답변을 믿고.... 제가 직접 폰 스톱워치로 셀수식과 VBA중 누가 더 포퍼먼스가 빠를까? 재 본적이 있습니다. 좀 황당하지만 저는 그 당시 완전 문외한 입장에서 최선을 다해서 쟀었습니다.
위는 1부터 100000까지 더하기 속도측정 VBA입니다. VBA로는 아주 간단하게 측정가능합니다. 셀수식의 속도측정은...
위 2개는 VBA와 셀수식 중 누가 더 빨리 [ 1부터 100000까지 더하기 ] 하나 측정하는 방법입니다. 속도는 0 초입니다. 정확히 말하면 0.000000001초일 겁니다. 너무 빨라 측정이 안되요. 그런데 이걸 스톱워치로 측정하려했으니 제가 정말 바보였었죠. 심지어 아아폰도 갤럭시도 스톱워치는 1/100 초가지만 잴 수 있죠. 설령 1/1000 초가 나온들 누가 손동작으로 그걸 측정할 수 있을까요? 엑셀에 한참 재미를 붙여 알아갈 때 별별 짓 퍼포먼스 추억쯤으로 기억하고 있습니다. 차후에 좋은 말씀 다시 전해주시면 감사드리겠습니다. 감사합니다.
대단하세요