HTTP 쓰기

쓰기 API 엔드포인트는 /db/write/{TABLE}이며, {TABLE}은 데이터를 저장할 테이블 이름입니다.

query API로도 INSERT 구문을 실행할 수 있지만, 요청마다 q 매개변수에 정적인 SQL 문자열을 구성해야 하므로 비효율적입니다. 데이터를 적재할 때는 INSERT와 동일하게 동작하는 write API를 사용하시는 것이 일반적입니다. 또한 write API를 사용하면 하나의 요청으로 여러 레코드를 한꺼번에 삽입할 수 있다는 장점이 있습니다.

매개변수

쓰기 매개변수

paramdefaultdescription
timeformatns시간 단위: s, ms, us, ns
tzUTC시간대: UTC, Local, 특정 지역
methodinsert데이터 쓰기 방식: insert, append

INSERT vs. APPEND

기본적으로 /db/write API는 INSERT INTO ... 구문을 사용해 데이터를 저장합니다. 소량의 레코드를 적재할 때는 append 방식과 성능 차이가 거의 없습니다.

수십만 건 이상의 대량 데이터를 적재할 때는 method=append 매개변수를 사용해 주십시오. 이렇게 지정하면 method=insert가 암묵적으로 적용되는 기본 동작 대신 Machbase Neo가 “append” 방식을 사용하도록 설정됩니다.

Content-Type 헤더

machbase-neo 서버는 Content-Type 헤더를 통해 입력 데이터 스트림의 형식을 판별합니다. 예를 들어 JSON 데이터는 Content-Type: application/json, CSV 데이터는 Content-Type: text/csv, 줄 단위 JSON은 Content-Type: application/x-ndjson을 지정해야 합니다.

Content-Encoding 헤더

클라이언트가 gzip으로 압축된 스트림을 전송할 경우 Content-Encoding: gzip 헤더를 설정하여 입력 데이터가 gzip으로 인코딩되었음을 machbase-neo에 알려야 합니다.

Inputs

JSON

이 요청 메시지는 INSERT INTO {table} (columns...) VALUES (values...) 구문과 동일한 구조입니다.

nametypedescription
dataobject데이터 본문 전체
data.columnsarray of strings컬럼 목록을 지정합니다.
data.rowsarray of tuples레코드 값 배열입니다.

JSON

{
    "data": {
        "columns":["name", "time", "value"],
        "rows": [
            [ "json-data", 1670380342000000000, 1.0001 ],
            [ "json-data", 1670380343000000000, 2.0002 ]
        ]
    }
}

Content-Type 헤더를 application/json으로 설정해 주십시오.

```http
POST http://127.0.0.1:5654/db/write/EXAMPLE
Content-Type: application/json

{
    "data": {
        "columns":["name", "time", "value"],
        "rows": [
            [ "json-data", 1670380342000000000, 1.0001 ],
            [ "json-data", 1670380343000000000, 2.0002 ]
        ]
    }
}
```
curl -X POST http://127.0.0.1:5654/db/write/EXAMPLE \
    -H "Content-Type: application/json" \
    --data-binary "@post-data.json"

압축 JSON

입력 스트림이 gzip으로 압축되었다면 Content-Encoding: gzip 헤더를 설정하여 machbase-neo에 알려야 합니다.

```http
POST http://127.0.0.1:5654/db/write/EXAMPLE
Content-Type: application/json
Content-Encoding: gzip

< /csv/post-data.json.gz
```
curl -X POST http://127.0.0.1:5654/db/write/EXAMPLE \
    -H "Content-Type: application/json" \
    -H "Content-Encoding: gzip" \
    --data-binary "@post-data.json.gz"

timeformat을 사용하는 JSON

시간 필드가 UNIX 에포크가 아닌 문자열 형식이라면 timeformattz 매개변수를 함께 지정해 주십시오.

```http
POST http://127.0.0.1:5654/db/write/EXAMPLE
    ?timeformat=DEFAULT
    &tz=Asia/Seoul
Content-Type: application/json

{
    "data": {
        "columns":["name", "time", "value"],
        "rows": [
            [ "json-data", "2022-12-07 02:32:22", 1.0001 ],
            [ "json-data", "2022-12-07 02:32:23", 2.0002 ]
        ]
    }
}
```
curl -X POST 'http://127.0.0.1:5654/db/write/EXAMPLE?timeformat=DEFAULT&tz=Asia/Seoul' \
    -H "Content-Type: application/json" \
    --data-binary "@post-data.json"
  • post-data.json
{
    "data": {
        "columns":["name", "time", "value"],
        "rows": [
            [ "json-data", "2022-12-07 02:32:22", 1.0001 ],
            [ "json-data", "2022-12-07 02:32:23", 2.0002 ]
        ]
    }
}

NDJSON

NDJSON(Newline Delimited JSON)은 각 줄이 유효한 JSON 객체인 스트리밍 형식입니다. 대용량 데이터나 스트리밍 데이터를 처리할 때 유용합니다.

이 요청 메시지 역시 INSERT INTO {table} (columns...) VALUES (values...) 구문과 동일한 구조입니다.

NDJSON

{"NAME":"ndjson-data", "TIME":1670380342000000000, "VALUE":1.001}
{"NAME":"ndjson-data", "TIME":1670380343000000000, "VALUE":2.002}

Content-Type 헤더를 application/x-ndjson으로 설정해 주십시오.

```http
POST http://127.0.0.1:5654/db/write/EXAMPLE
Content-Type: application/x-ndjson

{"NAME":"ndjson-data", "TIME":1670380342000000000, "VALUE":1.001}
{"NAME":"ndjson-data", "TIME":1670380343000000000, "VALUE":2.002}
```
curl -X POST http://127.0.0.1:5654/db/write/EXAMPLE \
    -H "Content-Type: application/x-ndjson" \
    --data-binary "@post-data.json"

timeformat을 사용하는 NDJSON

시간 필드가 UNIX 에포크가 아닌 문자열 형식이면 다음과 같이 작성할 수 있습니다.

{"NAME":"ndjson-data", "TIME":"2022-12-07 02:33:22", "VALUE":1.001}
{"NAME":"ndjson-data", "TIME":"2022-12-07 02:33:23", "VALUE":2.002}

timeformattz 매개변수를 함께 지정해 주십시오.

```http
POST http://127.0.0.1:5654/db/write/EXAMPLE
    ?timeformat=DEFAULT
    &tz=Local
Content-Type: application/x-ndjson

{"NAME":"ndjson-data", "TIME":"2022-12-07 02:33:22", "VALUE":1.001}
{"NAME":"ndjson-data", "TIME":"2022-12-07 02:33:23", "VALUE":2.002}
```
curl -X POST 'http://127.0.0.1:5654/db/write/EXAMPLE?timeformat=Default&tz=Local' \
    -H "Content-Type: application/x-ndjson" \
    --data-binary "@post-data.json"

CSV

다음 옵션은 본문이 CSV 형식일 때만 적용됩니다.

paramdefaultdescription
header Since v8.0.33skip: 첫 줄을 건너뜁니다.
columns: 헤더 줄이 테이블 컬럼명과 일치합니다.
headingfalse더 이상 사용하지 않습니다. heading=trueheader=skip과 동일합니다.
delimiter,필드 구분자

CSV 데이터에 헤더 줄이 포함되어 있다면 header=skip 쿼리 매개변수를 설정해 첫 줄을 무시하도록 하십시오.

헤더 줄에서 사용할 컬럼을 지정하고 싶다면 header=columns를 사용합니다. 헤더가 테이블 컬럼명과 일치해야 하며, 내부적으로 INSERT INTO TABLE(columns...) VALUES(...)의 컬럼 목록으로 활용됩니다.

헤더 줄이 없고 header 옵션을 생략(기본값, heading=false와 동일)한 경우에는 각 줄의 필드가 테이블의 모든 컬럼 순서와 정확히 일치해야 합니다. 이는 INSERT INTO TABLE VALUES(...) 구문에 대응하기 위해서입니다.

append 방식의 특성상 method=append와 함께 사용할 때는 header=columns 옵션이 동작하지 않습니다.

header=skip

header=skip을 지정하면 서버가 첫 줄을 무시하며, 데이터는 테이블 컬럼과 동일한 순서로 배치되어야 합니다.

NAME,TIME,VALUE
csv-data,1670380342000000000,1.0001
csv-data,1670380343000000000,2.0002

Content-Type 헤더는 text/csv로 지정해야 합니다.

```http
POST http://127.0.0.1:5654/db/write/EXAMPLE?header=skip
Content-Type: text/csv

NAME,TIME,VALUE
csv-data,1670380342000000000,1.0001
csv-data,1670380343000000000,2.0002
```
curl -X POST http://127.0.0.1:5654/db/write/EXAMPLE?header=skip \
    -H "Content-Type: text/csv" \
    --data-binary "@post-data.csv"

header=columns

CSV 필드 순서가 실제 테이블 컬럼과 다르거나 일부 컬럼만 포함되어 있다면 header=columns를 지정합니다. 그러면 서버는 첫 줄을 컬럼명으로 처리하며, 아래 예시는 내부적으로 INSERT INTO EXAMPLE (TIME, NAME, VALUE) VALUES(?, ?, ?)와 동일한 구문을 생성합니다.

TIME,NAME,VALUE
1670380342000000000,csv-data,1.0001
1670380343000000000,csv-data,2.0002

Content-Type 헤더는 text/csv로 지정해야 합니다.

```http
POST http://127.0.0.1:5654/db/write/EXAMPLE?header=columns
Content-Type: text/csv

TIME,NAME,VALUE
1670380342000000000,csv-data,1.0001
1670380343000000000,csv-data,2.0002
```
curl -X POST http://127.0.0.1:5654/db/write/EXAMPLE?header=columns \
    -H "Content-Type: text/csv" \
    --data-binary "@post-data.csv"

압축 CSV

입력 스트림이 gzip으로 압축되었다면 Content-Encoding: gzip 헤더를 설정해 machbase-neo에 알려야 합니다.

```http
POST http://127.0.0.1:5654/db/write/EXAMPLE?header=skip
Content-Type: text/csv
Content-Encoding: gzip

< /csv/post-data.json.gz
```
curl -X POST http://127.0.0.1:5654/db/write/EXAMPLE?header=skip \
    -H "Content-Type: text/csv" \
    -H "Content-Encoding: gzip" \
    --data-binary "@post-data.csv.gz"

timeformat을 사용하는 CSV

timeformattz 쿼리 매개변수를 함께 지정합니다.

```http
POST http://127.0.0.1:5654/db/write/EXAMPLE
    ?header=skip
    &timeformat=Default
    &tz=Asia/Seoul
Content-Type: text/csv

NAME,TIME,VALUE
csv-data,2022-12-07 11:39:32,1.0001
csv-data,2022-12-07 11:39:33,2.0002
```

예시

API의 자세한 설명은 Request endpoint and params를 참고해 주십시오.

테스트 테이블

```http
GET http://127.0.0.1:5654/db/query
    ?q=create tag table if not exists EXAMPLE (name varchar(40) primary key, time datetime basetime, value double)
```
curl -o - http://127.0.0.1:5654/db/query \
    --data-urlencode \
    "q=create tag table EXAMPLE (name varchar(40) primary key, time datetime basetime, value double)"

Time

이 예제에서 사용하는 샘플 파일의 시간 값은 초 단위 UNIX 에포크로 저장되어 있습니다. 따라서 데이터를 불러올 때는 timeformat=s 옵션을 지정해 주십시오. 다른 시간 정밀도로 저장된 데이터라면 해당 값에 맞춰 옵션을 수정해야 합니다. Machbase Neo는 기본적으로 시간 정밀도를 나노초(ns)로 가정하고 처리합니다.

JSON with epoch

```http
POST http://127.0.0.1:5654/db/write/EXAMPLE
    ?timeformat=s
Content-Type: application/json

{
  "data":  {
    "columns":["NAME","TIME","VALUE"],
    "rows": [
        ["wave.sin",1676432361,0],
        ["wave.sin",1676432362,0.406736],
        ["wave.sin",1676432363,0.743144],
        ["wave.sin",1676432364,0.951056],
        ["wave.sin",1676432365,0.994522]
    ]
  }
}
```

행 조회

```http
GET http://127.0.0.1:5654/db/query
    ?q=select * from EXAMPLE limit 10
```

CSV with epoch

CSV 데이터에 다음과 같이 헤더 줄이 있다면 header=skip 쿼리 매개변수를 지정해 주십시오.

```http
POST http://127.0.0.1:5654/db/write/EXAMPLE
    ?timeformat=s
    &header=skip
Content-Type: text/csv

NAME,TIME,VALUE
wave.sin,1676432361,0.000000
wave.cos,1676432361,1.000000
wave.sin,1676432362,0.406736
wave.cos,1676432362,0.913546
wave.sin,1676432363,0.743144

```

헤더 없는 CSV

```http
POST http://127.0.0.1:5654/db/write/EXAMPLE?timeformat=s
Content-Type: text/csv

wave.sin,1676432361,0.000000
wave.cos,1676432361,1.000000
wave.sin,1676432362,0.406736
wave.cos,1676432362,0.913546
wave.sin,1676432363,0.743144
```

CSV

Insert

```http
POST http://127.0.0.1:5654/db/write/EXAMPLE
    ?timeformat=Default
Content-Type: text/csv

wave.sin,2023-02-15 03:39:21,0.111111
wave.sin,2023-02-15 03:39:22.111,0.222222
wave.sin,2023-02-15 03:39:23.222,0.333333
wave.sin,2023-02-15 03:39:24.333,0.444444
wave.sin,2023-02-15 03:39:25.444,0.555555
```
```http
GET http://127.0.0.1:5654/db/query
    ?q=select * from EXAMPLE limit 10
    &timeformat=Default
    &format=csv
```

Append

대용량 CSV 파일을 적재할 때는 “append” 방식을 사용하면 “insert” 방식보다 여러 배 빠르게 입력할 수 있습니다.

```http
POST http://127.0.0.1:5654/db/write/EXAMPLE?timeformat=s&method=append
Content-Type: text/csv

wave.sin,1676432361,0.000000
wave.cos,1676432361,1.000000
wave.sin,1676432362,0.406736
wave.cos,1676432362,0.913546
wave.sin,1676432363,0.743144
```

시간대를 지정한 CSV

```http
POST http://127.0.0.1:5654/db/write/EXAMPLE
    ?timeformat=Default
    &tz=Asia/Seoul
Content-Type: text/csv

wave.sin,2023-02-15 12:39:21,0.111111
wave.sin,2023-02-15 12:39:22.111,0.222222
wave.sin,2023-02-15 12:39:23.222,0.333333
wave.sin,2023-02-15 12:39:24.333,0.444444
wave.sin,2023-02-15 12:39:25.444,0.555555
```

UTC 기준으로 조회

```http
GET http://127.0.0.1:5654/db/query
    ?q=select * from EXAMPLE limit 10
    &timeformat=Default
    &format=csv
```

RFC3339

```http
POST http://127.0.0.1:5654/db/write/EXAMPLE
    ?timeformat=RFC3339
Content-Type: text/csv

wave.sin,2023-02-15T03:39:21Z,0.111111
wave.sin,2023-02-15T03:39:22Z,0.222222
wave.sin,2023-02-15T03:39:23Z,0.333333
wave.sin,2023-02-15T03:39:24Z,0.444444
wave.sin,2023-02-15T03:39:25Z,0.555555
```

UTC 기준으로 조회

```http
GET http://127.0.0.1:5654/db/query
    ?q=select * from EXAMPLE limit 10
    &format=csv
    &timeformat=RFC3339
```

시간대를 포함한 RFC3339Nano

```http
POST http://127.0.0.1:5654/db/write/EXAMPLE
    ?timeformat=RFC3339Nano
    &tz=America/New_York
Content-Type: text/csv

wave.sin,2023-02-14T22:39:21.000000000-05:00,0.111111
wave.sin,2023-02-14T22:39:22.111111111-05:00,0.222222
wave.sin,2023-02-14T22:39:23.222222222-05:00,0.333333
wave.sin,2023-02-14T22:39:24.333333333-05:00,0.444444
wave.sin,2023-02-14T22:39:25.444444444-05:00,0.555555
```

America/New_York 시간대로 조회

```http
GET http://127.0.0.1:5654/db/query
    ?q=select * from EXAMPLE limit 10
    &format=box
    &timeformat=RFC3339Nano
    &tz=America/New_York
```

Timeformat

```http
POST http://127.0.0.1:5654/db/write/EXAMPLE
    ?timeformat=Default
Content-Type: text/csv

wave.sin,2023-02-15 03:39:21,0.111111
wave.sin,2023-02-15 03:39:22.111111111,0.222222
wave.sin,2023-02-15 03:39:23.222222222,0.333333
wave.sin,2023-02-15 03:39:24.333333333,0.444444
wave.sin,2023-02-15 03:39:25.444444444,0.555555
```

UTC 기준으로 조회

```http
GET http://127.0.0.1:5654/db/query
    ?q=select * from EXAMPLE limit 10
    &format=csv
    &timeformat=Default

```

사용자 정의 Timeformat

  • 뉴욕 시간대를 기준으로 hour:min:sec-SPLIT-year-month-day 형식 사용
```http
POST http://127.0.0.1:5654/db/write/EXAMPLE
    ?timeformat=03:04:05.999999999-SPLIT-2006-01-02
    &tz=America/New_York
Content-Type: text/csv

wave.sin,10:39:21-SPLIT-2023-02-14 ,0.111111
wave.sin,10:39:22.111111111-SPLIT-2023-02-14 ,0.222222
wave.sin,10:39:23.222222222-SPLIT-2023-02-14 ,0.333333
wave.sin,10:39:24.333333333-SPLIT-2023-02-14 ,0.444444
wave.sin,10:39:25.444444444-SPLIT-2023-02-14 ,0.555555
```

행 조회

```http
GET http://127.0.0.1:5654/db/query
    ?q=select * from EXAMPLE limit 5
    &format=csv
    &timeformat=2006-01-02 03:04:05.999999999
    &tz=America/New_York
```
최근 업데이트