효율적인 SQL 구문은 아니지만, 가벼운 SQL 쿼리문에서는 WHERE절에 `IN`을 이용한 Multiple Value에 대한 매칭을 하는 경우가 종종 있습니다. 안타깝게도 Presto 쿼리 신텍스에는 동일한 구문이 존재하지는 않습니다. 다만, 비슷한 방식으로 사용하는 구문이 존재합니다.
-- Presto Query
SELECT id, name, department
FROM data_source.default
WHERE department = ANY (VALUES 'ORG1', 'ORG2')
Presto의 WHERE 구문에서는 ANY라는 키워드를 이용할 수 있습니다. 이후 VALUES 키워드에 이어서 해당 컬럼에서 찾고자 하는 여러 값을 콤마로 구분해서 넣어주면 됩니다. 보다 자세한 구문 설명은 아래 링크에서 참고하세요.
influxDB 는 시계열 DB (TSDB) 입니다. 일반적인 SQL 문장을 사용할 수 있다보니 종종 TSDB 가 아닌 RDB 로 착각할때가 많습니다. 때문에 일어나는 해프닝이 참 많은데요, <SELECT INTO> 를 이용하여 Measurement 간에 데이터를 옮길 때도 종종 문제가 생기곤 합니다.
사실 저 역시 infludDB 를 많이 사용해 보지는 못했습니다. 어쩌다 보니 다른 분이 운영하던 Graphite 에 저장하고 있던 데이터가 더 이상 적재되지 않고 있어 어디서부터 손을 대볼까하다 "새롭게 해보자!" 는 마음으로 influxDB 를 구성해서 쓰는 정도이기 때문입니다. 아시겠지만 무언가를 할 때마다 매번 새로운 기분이라...
우선, influxDB 에서 <SELECT INTO> 구문을 사용하기 전에 공식 문서를 한 번 읽어보는 것을 추천드립니다. influxDB 의 공식문서가 마음에 드는 점 중 하나는 설명만 나열하는 것이 아니라 샘플 쿼리와 같은 예시가 중간중간에 소개된다는 점입니다. 설명을 읽는 것도 중요하지만 샘플을 가지고 이해하는 것이 더 좋을떄도 많기 때문이지요!
여전히 많은 사람들이 RDB 사고 방식으로 TSDB 를 보고 있나 봅니다. 공식 문서에서도 <Common Issues> 항목으로 <Missing data> 가 있어서 빠르게 해결할 수는 있었습니다. TSDB 에 대한 인식, InfluxDB 의 Tag 에 대한 이해 없이 막 사용하다 보니 발생한 해프닝이겠죠? 사실 이렇게 글을 적고는 있지만 현업에서의 이슈 해결이 급하다 보니 Tag 에 대해 이해할 수 있는 문서들을 더 열람해 보지는 않았습니다. 공부하는대로 다음 포스팅으로 적을 것을 약속합니다 :-)
제 경우의 이슈는 Issue 1 에 설명된 부분이었습니다. RDB 에서 의례 했던 것처럼 아래의 구문으로 특정 값을 가진 데이터를 다른 Measurement 로 옮기려는 것이 제 의도였습니다. 하지만, where 절의 값을 바꾸면서 3회 정도 쿼리를 수행했지만, 목적지의 레코드 갯수는 턱없이 적었습니다.
SELECT * INTO "new_table" FROM "old_table" WHERE "type"='audio'
SELECT * INTO "new_table" FROM "old_table" WHERE "type"='video'
SELECT * INTO "new_table" FROM "old_table" WHERE "type"='etc'
공식 문서의 Issue 1 에 나온 것처럼 <현재 Measurement 의 태그(tags)를 새로운 Measurement 의 필드(Fields)로 컨버트한다> 는 동작 때문이었습니다. 인지하지 못한 사이에 현재 Measurement 의 "type" 은 태그였던 것입니다. 왜냐구요? 아직 공부하지 못했습니다 ㅜㅜ 여튼 그런연유로 데이터가 계속 겹쳐 써지면서 제대로 이관이 되지 않았던 상황이었습니다.
역시나 문서에 나온것처럼 원래의 태그를 유지하기 위해서는 "GROUP BY *" 구문을 추가하여 사용하여 문제를 해결했습니다. 새로운 데이터베이스에 대한 이해가 부족한 상태에서 필요한 결과물을 빨리 얻으려다보니 생긴 해프닝입니다. 여러분들도 혹시 유사한 문제를 만난다면 구문을 살펴보고 GROUP BY 를 추가해 주면 이슈를 벗어날 수 있을겁니다!
SELECT * INTO "new_table" FROM "old_table" WHERE "type"='audio' GROUP BY *
SELECT * INTO "new_table" FROM "old_table" WHERE "type"='video' GROUP BY *
SELECT * INTO "new_table" FROM "old_table" WHERE "type"='etc' GROUP BY *
비지니스 로직에서 데이터베이스 관련 구문을 사용하지 않기 위해 종종 Stored Procedure 로 많은 로직을 옮기곤 합니다. View 와 Logic 을 분리한다는 차원 이외에도 보안적인 측면이나 불필요한 에러를 막기 위한 것 이외에도 Strongly Typed 프로그래밍의 명확한 적용을 위해서라도 유용한 방법입니다.
SP 를 사용하는 몇 안되는 단점 중 하나가 에러처리 부분이 아닐까 싶습니다. NoPD 군은 그동안 SQL 구문 날코딩을 사랑하다 최근 SP 로 로직을 모두 옮기어 조그만 프로젝트를 하나 하고 있는데, 여기저기 검색하다가 정갈하게 정리된 내용을 발견해서 공유할까 합니다.
SELECT @err = @@ERROR, @row = @@ROWCOUNT
IF @err != 0 OR @row != 1
BEGIN
SET @result = 'sp_commitContent|컨텐츠 수정에 문제가 있습니다. 관리자를 컨택해 주세요.'
GOTO ERROR
END
ERROR:
RAISERROR(@result, 11, 1)
RETURN
@@ERROR 값과 @@ROWCOUNT 값을 같이 이용하여 쿼리가 정상적으로 수행 되었는지를 확인하는 방법이 바로 그것입니다. 이미 다들 아시는 내용일지 모르겠으나 DB 를 날쿼리 중심으로 쓰던 NoPD 군에게는 새로운 SQL 구문이 아닐 수 없습니다! ^^
웹 사이트를 개발할 때 가장 고민되는 부분 중 하나가 페이징입니다. 보통 MS-SQL 에서는 중첩 쿼리를 이용하여 TOP n 스타일의 쿼리를 하는 경우가 많은데, 퍼포먼스 측면에서 아주 쥐약인 경우가 많습니다. 오늘 소개해 드리는 페이징 쿼리는 일단 속도가 그리 느리지 않고 중첩 쿼리에 비해 부하가 적을 것으로 추정(!)하고 있습니다 ^^;
with rn
as
(
select EmailAddress, ROW_NUMBER() over (order by FirstName desc) as rn
from Person.Contact
)
select FirstName, LastName, rn
from Person.Contact join rn on Person.Contact.EmailAddress = rn.EmailAddress
where rn between 5 and 10
with 문을 이용하여 ROW_NUMBER() 로 항목에 넘버링을 한 다음 필요한 구간을 where 절에 기술하여 페이징하는 방식입니다. Execution Plan 으로 봤을 때 비용이 많이 들지 않는 것 같습니다만 실제로 효과가 있는지는 실데이터로 적용해서 돌려봐야할 것 같습니다 ^^ 참고로 위의 예제는 AdventureWorks 샘플 DB 를 사용했습니다.