분류

2020년 9월 20일 일요일

mariadb CONNECT BY, 시간계산, 프로시저 만들기 요약.

개요 

오픈소스 기반 프로젝트를 수행하면서 MARIADB라는 녀석을 접하게 되었습니다. 기존의 ORACLE환경과는 다르기에 프로시저를 짜는데 애를 먹는 바람에 정리를 하려 합니다. 

그리고 프로그램 설정의 오류 때문인지 LOOP 문을 돌릴 경우 발생되는 데이터가 초당 20건밖에 되지 않는 기이한 현상이 있었는데 이런 건 PGA 메모리가 부족하든 CPU를 프로그램에 할당한 것이 없든 여러 환경적 문제가 있는 것 같습니다. 하지만 이런 문제를 모두 정리하기엔 시간이 부족하기에 루프문을 최소화해서 처리하는 해법을 찾아보았습니다. 


1. CONNECT BY LEVEL 문을 통한 여러 행 생성하기 

마땅히 CONNECT BY 문이 없어 애를 먹는 과정에서 RECURSIVE 관계를 WITH문을 통해 만들 수 있는 것을 발견하였습니다. 

저는 임의의 행 데이터 집합을 가상의 형태로 만들어야 하는 프로시저를 만들어야 합니다. 따라서 기존 작성했던 쿼리와 비교하며 검색을 해보았습니다. 

ORACLE : 

SELECT * FROM 
   임의테이블 A
   , (SELECT LEVEL AS LV FROM DUAL CONNECT BY LEVEL <=10)  B

위와 같은 쿼리를 통해 단일 데이터를 10배 뻥튀기 하는 과정이 필요했습니다. 해당 쿼리는 아래와 같이 변경됩니다. 

MARIADB : 


WITH RECURSIVE a(n) AS (
  SELECT
    UNION ALL 
   SELECT  n+1 
   FROM a
   WHERE n < 10  /*최대 레벨에 해당하는 수치 입력*/
)
SELECT  n, b.* 
FROM  
   a
  ,  임의테이블 b

재귀 호출에 대한 자세한 스펙은 아래 문서를 참조하시면 됩니다. 

간단하게 말하자면 WITH RECURSIVE 뒤편에 들어있는 a(n)
a <--테이블이름 (n) 컬럼이름의 형태로 활용할 수 있으며 해당 리커시브 내에서도 재귀를 사용할 수 있습니다. a(n)은 재귀명(컬럼명1,컬럼명2) 처럼 다중 행과 컬럼을 포함할 수 있는 구조가 됩니다. 


2. 시간에 대한 계산하기 

가. 시간 차 계산 

시간의 차이에 대한 계산은 TIMESTAMPDIFF 함수를 사용합니다. 

ORACLE : 
SELECT  TO_DATE('날자','YYYY-MM-DD') - SYSDATE FROM  DUAL; 
같은 함수를 이용하여 시간은 *24 분은 *24*60 초는 *24*60*60을 해서 구했던 것 과 다릅니다. MARIADB 쪽이 조금 더 명시성이 확보되어 좋다는 생각이 듭니다. 

MARIADB : 
SELECT  TIMESTAMPDIFF(SECOND, '시작일자', '종료일자') ; 
위와 같은 구문을 이용하면 두 날짜 차이의 초단위 차를 계산을 수행해줍니다. 
참고로 SECOND는 YEARMONTH, DAYHOUR, MINUTE 등으로 변경하여 해당 단위에 대한 차를 구할 수 있습니다. 

나. 시간의 증감 계산 

TIMESTAMPADD 함수를 통해 시간에 대한 증가와 감소를 계산할 수 있습니다. 

사용문법은 이렇습니다. 
SELECT  TIMESTAMPADD (단위, 증감수치, '날짜') 
ex) SELECT  TIMESTAMPADD (SECOND, 60, '2020-01-01 20:11:25') 
단위에 들어갈 수 있는 수치는 위와 동일하게 
YEARMONTHDAYHOURMINUTE, SECOND 입니다. 

3. 프로시저 

저장 프로시저, 실행 프로시저를 만드는 방법은 오라클과 약간 다릅니다. 

가. 저장 프로시저 

ORACLE :
CREATE OR REPLACE PROCEDURE 프로시저명(변수1 IN 타입, ...)
IS 
커서, 변수 선언 
변수명 데이터타입; 
/*예:) DECLARE TMPVAL VARCHAR(10);  */
BEGIN 
수행내용 .. 
       /*변수에 값을 넣을 경우 */
       변수명 := 값; 

       /*루프유형1*/
       FOR 커서명 IN  1..9 
       LOOP  
           처리내용  ; 
       END LOOP
       /*루프유형2*/             
       FOR  커서2 IN (SELECT COL1,COL2 FROM 테이블  ...)
       LOOP  
           INSERT INTO 테이블3
           (커서2.COL1, 커서2.COL2); 
       END LOOP; 
END
 
MARIADB : 
CREATE OR REPLACE PROCEDURE 프로시저명(변수1 IN 타입, ...)
BEGIN 
   DECLARE  변수명 타입; 
   /*예:) DECLARE TMPVAL VARCHAR(10);  */
   /*  위의 변수 선언이 기본 형식이나 임의 값을 사용할 수 있다. */
   /*예 ) SET @tmp = '';  등의 형태로 활용할 경우 변수의 선언이 필요 없음*/ 
   수행내용 .. 
     /*변수에 값을 넣는 경우 */
      SET 변수명 = 값; 
   /*루프유형1*/
       FOR 커서명 IN  1..9 
       DO
           처리내용  ; 
       END FOR; 
       /*루프유형2*/             
       FOR  커서2 IN (SELECT COL1,COL2 FROM 테이블  ...)
       DO
           INSERT INTO 테이블3
           (커서2.COL1, 커서2.COL2); 
       END FOR;     
END 
ORACLE과 큰 차이 없이 사용할 수 있다. 
LOOP와 DO의 차이 정도, 그리고 변수를 임의로 지정할 수 있는 부분, 그리고 변수에 값을 넣는 것이 ORACLE 의 변수 := 값  -> MYSQL SET 변수 = 값; 정도의 차이만 있을 뿐 기본적인 부분이 같다. 

LOOP문 : 
LOOP문에서는 간혹 ORACLE 에서 LOOPEXIT 를 활용하는 부분이 다르다. 
ORACLE : 
LOOP
   수행로직 ;
   EXIT WHEN 탈출조건
END LOOP

MARIADB  : 
REPEAT 
   수행로직 ;
    UNTIL 탈출조건 
END  REPEAT ; 

다. 임의 실행 프로시저 

보편적으로 저장 프로시저와 임의 수행을 위해 (개발, 테스트시) 사용하는 프로시저는 다음과 같은 차이가 있다. 

ORACLE : 
DECLARE  
    변수선언 
BEGIN 
    로직 
END

MARIADB : 
DELIMITER|
   BEGIN NOT ATOMIC
     변수선언
     로직수행 
   END
DELIMITER; 
이 부분 역시 문법 이외에 별 차이가 없다. 
ORACLE에서는 DECLARE  나 BEGIN 만으로 수행 프로시저를 즉시 실행 시킬 수 있는 것과 MARIADB에서는 DELIMITER라는 명령어로 수행하는 것 만 다르다. 다만 ORACLE 프로시저와 MARIADB 프로시저에서는 눈에 띄게 다른 점이 LOOP 문을 활용할 경우 초당 처리 건수의 치이가 난다. ORACLE에서는 프로시저에서 LOOP를 돌려 수천 건의 임의데이터를 생성할 수 있었던 반면 MARIADB는 초당 20건밖에 데이터가 생성되지 않았으며, 아직 원인 규명이 되지 않은 상태다. 

다. 프로시저 만들기 

임의의 기간에 해당하는 데이터를 자동 생성하는 프로시저를 만들 경우 샘플을 만들어보자면 아래와 같다. 

/*테이블 생성 */

CREATE TABLE TMPTBL(
  STIME timestamp
  , ETIME timestamp
  , VALUE int
); 

/*임의 값 생성  현재시간 + 60초 1 +60초 2*/

INSERT INTO TMPTBL
VALUES(NOW()TIMESTAMPADD (SECOND, 60, NOW(), 1)
, (TIMESTAMPADD (SECOND, 60, NOW()), TIMESTAMPADD (SECOND, 60, TIMESTAMPADD (SECOND, 60, NOW())), 2); 


/*기간만큼 데이터를 늘리는 저장 프로시저 생성 * /

CREATE OR REPLACE PROCEDURE testProcedure(in prTime timestamp)  
BEGIN
  for rec IN  (SELECT  STIME, ETIME, VALUE FROM TMPTBL)
  do 
SET @itv = TIMESTAMPDIFF(SECOND, rec.STIME, rec.ETIME); /*기간차를 초로*/
INSERT INTO TMPTBL(STIME, ETIME, VALUE) 
WITH 
RECURSIVE  list(n) 
AS (
SELECT  1
UNION ALL
SELECT  n+1 FROM  list
WHERE n < @itv /*초만큼 LEVEL생성*/
)
SELECT  
 TIMESTAMPADD(SECOND, list.n, rec.STIME) 
TIMESTAMPADD(SECOND, list.n, rec.ETIME)
, rec.VALUE*n 
FROM  list
  END for; 
END;

/*기간만큼 데이터를 늘리는 즉시 수행 프로시저 */

DELIMITER |
BEGIN NOT ATOMIC
for rec IN  (SELECT  STIME, ETIME, VALUE FROM TMPTBL)
  do 
SET @itv = TIMESTAMPDIFF(SECOND, rec.STIME, rec.ETIME); /*기간차를 초로*/
INSERT INTO TMPTBL(STIME, ETIME, VALUE) 
WITH 
RECURSIVE  list(n) 
AS (
SELECT  1
UNION ALL
SELECT  n+1 FROM  list
WHERE n < @itv /*초만큼 LEVEL생성*/
)
SELECT  
 TIMESTAMPADD(SECOND, list.n, rec.STIME) 
TIMESTAMPADD(SECOND, list.n, rec.ETIME)
, rec.VALUE*n 
FROM  list 
  END for; 
END|
DELIMITER ;  

수행결과 




이번은 MYSQL이나 MARIADB에서 CONNECTION BY 구문, 시간계산과 프로시저를 생성하는 방법 , 그리고 PLSQL을 이용한 임의 데이터 생성하는 방법등 여러가지를 한꺼번에 정리해보았습니다. 개인적으로는 연계되어 사용까지가 한쿨이라고 생각하기에 이런 정리 방식이 좋은 것 같네요. 

실무에 조금이라도 도움이 되었으면 좋겠네요. 이상입니다. 

기타 

mariadb 의 실행 프로시저 begin not atomic 프로시저 내에서 여러 테이블을 호출하고 사용할 경우 다수의 트랜잭션이 동시 처리되는 환경에서 dead lock 오류가 발생하는 것을 확인 하였습니다. 또한 동일 프로그램을 spring 환경에서 개별 SQL MAPPER로 분리할 경우 해당 문제가 해결되는 것도 확인하였습니다. 

2020년 9월 7일 월요일

샤오미 POCO F2 PRO 개봉 부터 LTE 유심기변(개통) 하기

개요 

휴대폰이 고장 났습니다. 성능도 날이 갈수록 느려지고, 지문 인식 기능도 오락가락 합니다. 31개월 사용했습니다. 그래서 바꾸려고 알아봤습니다. 중국 직구폰 개통기 시작하겠습니다. 


5G 시장이 열리면서 스마트폰이 참 비싸졌습니다. 국내 상품으로는 5G가 아니더라도 신품은 거의 100만원을 호가하는 비싼 제품을 파는 상황에서 기존 제품보다 느리지 않은 휴대폰을 찾는 것이 쉽지는 않았습니다. 미디테크 멀티코어나 ARM 계열의 제품은 성능이 좋지 않고, 스냅 드래곤의 나름 최신 버전인 865를 끼워 넣은 제품은 국내에서 모두 120만원을 호가하는 상황이었습니다. (주문 할 때는 말이죠. 앞으로 연말 되면 할인이다 뭐다 많겠죠. )

다나와 스냅드래곤 865 검색결과

80만원 UNDER로는 모두 중국 제품이기에 이전에 가성비로 소문이 났던 POCO F2를 주문하기로 했습니다. 

샤오미 POCO F2 374$

본문의 내용은 1. 구매 및 개봉 -> 2. 통신사 기기등록 -> 3. 유심 활성화 순으로 되어있습니다. 


1. 구매 및 개봉 

중국 직구를 진행 할 경우 포코폰 2가 374$ 약 45만원에 배송비 없이 구매할 수 있었습니다. 그리고 한중 FTA에 의해 휴대폰 전자제품은 관세 없이 들어올 수 있다고 합니다. 혹여 부가세가 날아올까 기다렸는데 세관을 통하지 않고 들어왔습니다. 통관 기록이 전혀 없습니다. 원인은 제가 알 수 없습니다. 통관 기록이 없기에 준비한 부가세는 세이브 되었습니다. 


배송은 8월 17일(구매당일) 시작하여 9월3일 도착 17일 걸렸습니다. 어떤 이유인지 중국 제품이 홍콩에 도착하여 배를 타고 한국으로 온 것 같습니다. 원인은 아마 배터리 폭파 때문에 리듐이온 배터리가 들어있는 제품은 항공 운송을 안 해주기 때문 아닌가 합니다. ?!(홍콩과 붙어있는 지역일 수 있습니다.)

외형은 뭐 제가 설명하지 않아도 여러 동영상, 혹은 쇼핑 사이트에서 잘 보실 수 있을 거라고 믿습니다. 개인적으로 다르다고 느껴진 부분은 2가지 정도 입니다. 

팝업 셀피카메라. 

화면 지문인식 

화면 지문인식
처음엔 화면에 지문인식이 되는 줄 모르고; 지문인식기가 어디에 있나 한참 찾았습니다. 

그 외 박스 구성품은 다음과 같습니다. 
1. 휴대폰 
(보호필름 부착상태로 옵니다. 글래스필름 딸려왔는데 실수로 위에다 붙여서 버렸어요. )
2. 충전기
3. 충전 케이블 
4. 설명서1부, 보증서 1부
5. 투명 케이스 (기본)
6. 추가 구매 글래스 필름, 보호커버 
7. 휴대폰 가로 스탠드
8. 유심 교체용 핀

휴대폰 스탠드는 정말 쓰기 불편한 클립 스텐드이고, 기본품으로 딸려오는 투명 케이스는 뒷면의 카메라를 보호할 수 없는 형태입니다. 따라서 nillkin 케이스는 필수인 것 같습니다. 사진은 클릭하면 확대 됩니다. 

구성품 전체 

클립 스탠드

클립스탠드 사용 시

기본 투명케이스 케이스를 씌워도 카메라가 돌출됨, 또한 RFID(NFC) 인식률이 하락함.  

번들로 함께 구매한 nillkin 케이스
케이스가 카메라 앞으로 돌출되어 카메라 보호 합니다.


2. 통신사 기기 등록

국내에는 POCO폰 F2를 구매한 사람이 해당 사이트에서는 저를 포함하여 총 3명이었고, 현재 개통 소식을 알리는 것은 제가 첫 번째 인 것 같습니다. 일단 전 두 가지를 모두 진행했습니다. 일반 통신사 약정 할인을 받는 고객은 유심기변을 할 경우 단말기가 등록되지 않은 상태에선 할 수 없다 하여 사용하는 통신사인 LG유플러스에 방문하여 IMEI 등록을 수행하였습니다. IMEI 등록은 복불복입니다. 직영점에서 진행하였는데 2곳을 방문하였고, 그중 한 곳에서는 '우리는 샤오미 취급 안 해요' 같은 헛소리를 시전 했답니다. 유플러스 분들은 제가 이미 했으니 가서 하시면 됩니다. 

IMEI 코드는 휴대폰 뒤편 하단에 스티커로 붙어있어 훼손되기 쉽습니다. 떼더라도 등록하고 때세요. 또한 USIM은 듀얼 유심을 지원하기에 IMEI도 2개이니 혹여 하나가 고장 날 것을 대비해 2개를 모두 등록하였습니다. 

기기 하단의 심카드보다 조금 큰 심 슬롯, 앞뒤 2개입니다. 


하지만 IMEI등록을 마친 후에도 개통이 되지 않았습니다. 따라서 유심 활성화 절차에 들어갔습니다. 


3. 유심활성화 

전화기 다이얼을 눌러 해당 번호를 누르면 됩니다. 

*#*#86583#*#*

위 동영상과 같이 carrier check was disabled  과 enable 이 반복되는 토글 입력입니다. 혹여 실수로 두 번 눌렀다고 해도 최종적으로 "carrier check was disabled" 로 만드시면 되니 걱정 없이 누르시면 됩니다. 그리고 재부팅을 2,3회 하시면 됩니다. 5G / 4G / 3G를 모두 지원하나 개통 2일차인 현재 이동 중 기지국이 바뀌는 국면에서 재부팅을 해야 하는 경우가 종종 있습니다. 

"SIM카드를 활성화 할 수 없습니다." 라는 메시지가 휴대폰이 개통되지 않은 상태에서는 발생합니다. 위 방법으로 통신사 체크를 해제하면 기본적으로 됩니다. 다만 가끔 샤오미 계정에서 폰 번호를 잘못 입력 한 상태로 휴대폰 분실 찾기를 설정해 놓은 경우 휴대폰 분실 찾기 기능에서 유심을 엑세스 하면서 오류메시지를 내보내기도 한다고 합니다. 하지만 근본적인 것은 휴대폰이 정상 개통 상태여야 하는 점을 명심하세요. 

샤오미 계정에 등록된 ID에 대한 확인은 설정 ->MI계정 -> 계정 보안 ->복구 전화 순으로 들어가셔서 확인하면 됩니다. 

해외직구 폰 구매 및 등록을 하시는 분들에게 도움이 되었으면 좋겠네요. 

이상입니다. 

2020.10.28 개통 2개월차 현재에도 도심에서는 기지국 전환시 lte를 못찾다가 3분 후 접속되는 현상이 있습니다. 주말에 자전거로 시골 라이딩을 할때는 100km 이상 달려도 끊김이 발생하지 않는 것으로 보아 5G망을 통한 연결이 되거나 5G, 4G가 모두 지원되는 기지국에서 오류가 발생하는 것 같습니다. 즉. 기기문제는 아니고 통신사 5G가 문제입니다. 재부팅 하면 즉시 접속되거나 3-5분가량 지나면 자동으로 접속됩니다.