mysql
mysql
원격 MySQL 서버에 저장된 데이터에 SELECT와 INSERT 쿼리를 수행할 수 있게 해주는 테이블 함수예요.
출처: 문서
본문
원격 MySQL 서버에 저장된 데이터에 SELECT와 INSERT 쿼리를 수행할 수 있게 해줘요.
문법 (Syntax)
mysql({host:port, database, table, user, password[, replace_query, on_duplicate_clause] | named_collection[, option=value [,..]]})
인자 (Arguments)
| 인자 | 설명 |
|---|---|
host:port |
MySQL 서버 주소예요. |
database |
원격 데이터베이스 이름이에요. |
table |
원격 테이블 이름 또는 MySQL에 그대로 전달되는 쿼리예요. |
user |
MySQL 사용자예요. |
password |
사용자 비밀번호예요. |
replace_query |
INSERT INTO 쿼리를 REPLACE INTO로 변환하는 플래그예요. 가능한 값: - 0 - 쿼리가 INSERT INTO로 실행돼요. - 1 - 쿼리가 REPLACE INTO로 실행돼요. |
on_duplicate_clause |
INSERT 쿼리에 추가되는 ON DUPLICATE KEY on_duplicate_clause 표현식이에요. replace_query = 0일 때만 지정할 수 있어요 (replace_query = 1과 on_duplicate_clause를 동시에 넘기면 ClickHouse가 예외를 발생시켜요). 예: INSERT INTO t (c1,c2) VALUES ('a', 2) ON DUPLICATE KEY UPDATE c2 = c2 + 1; 여기서 on_duplicate_clause는 UPDATE c2 = c2 + 1이에요. ON DUPLICATE KEY 절과 함께 사용할 수 있는 on_duplicate_clause의 종류는 MySQL 문서를 참고하세요. |
인자는 네임드 컬렉션으로도 전달할 수 있어요. 이 경우 host와 port를 따로 지정해야 해요. 프로덕션 환경에서는 이 방식을 권장해요.
=, !=, >, >=, <, <= 같은 간단한 WHERE 절은 현재 MySQL 서버에서 실행돼요.
나머지 조건과 LIMIT 샘플링 제약은 MySQL 쿼리가 끝난 뒤에만 ClickHouse에서 실행돼요.
TLS/SSL
MySQL로의 암호화 연결 자격 증명은 네임드 컬렉션 키(또는 키-값 인자)로 전달돼요:
| 파라미터 | 설명 |
|---|---|
ssl_ca_pem |
MySQL 서버 인증서를 검증하는 데 사용되는 CA 인증서의 내용이에요. |
ssl_cert_pem |
인증서 기반 인증을 위한 클라이언트 인증서의 내용이에요. |
ssl_key_pem |
ssl_cert_pem에 속하는 개인 키의 내용이에요. |
이 값들은 해당 PEM 파일의 내용이며, 네임드 컬렉션 또는 쿼리에 복사할 수 있어요. 비밀번호와 같은 방식으로 로그와 SHOW 쿼리에서 마스킹돼요.
동일한 자격 증명을 서버의 파일 경로로도 줄 수 있어요. ssl_ca, ssl_cert, ssl_key에서요 — 하지만 서버 구성 파일에 정의된 네임드 컬렉션에서만 가능하고, 그런 값은 쿼리에서 재정의할 수 없어요. 서버는 자기 권한으로 그 파일들을 여는데, SQL에서 경로를 받게 되면 MySQL 소스를 정의할 수 있는 모든 사용자가 로컬 파일시스템을 살펴보고, 스스로 읽을 권한이 없는 인증서와 키로 인증할 수 있게 되기 때문이에요.
테이블 이름 대신 쿼리 전달 (Passing a query instead of a table name)
테이블 이름 대신, 세 번째 인자는 MySQL에 그대로 전달되는 SELECT 쿼리일 수 있어요. 결과 테이블의 구조는 쿼리 결과에서 유추돼요. 쿼리는 서브쿼리로 쓰거나 query 함수로 감쌀 수 있어요:
SELECT * FROM mysql('localhost:3306', 'test', (SELECT a, b FROM t1 JOIN t2 USING (id) WHERE a > 0), 'user', 'password');
SELECT * FROM mysql('localhost:3306', 'test', query('SELECT a, b FROM t1 JOIN t2 USING (id) WHERE a > 0'), 'user', 'password');
이것은 조인, 집계 또는 기타 처리를 MySQL로 푸시다운하는 데 유용해요. 이런 테이블은 읽기 전용이에요: INSERT할 수 없어요. 동일한 문법은 MySQL 테이블 엔진에서도 지원돼요.
서브쿼리 형태 (SELECT ...)는 ClickHouse가 파싱하고 MySQL 방언(백틱 식별자 따옴표)으로 재직렬화한 뒤 서버에 보내요. 따라서 유효한 ClickHouse SQL이어야 해요. ClickHouse가 파싱하지 못하는 MySQL 전용 문법을 전달하려면 텍스트가 MySQL에 그대로 전송되는 query('...') 형태를 사용하세요.
주변 ClickHouse 쿼리의 어떤 외부 WHERE, LIMIT, 집계 등도 전달된 쿼리에는 푸시다운되지 않아요 — 전체 쿼리 결과를 가져온 뒤 ClickHouse에서 적용돼요. MySQL에서 읽는 데이터를 제한하려면 전달된 쿼리 안에 필터를 넣으세요. external_table_strict_query = 1로 설정하면 테이블 함수 컬럼에 대한 외부 필터는 로컬로 적용되는 대신 예외로 거부돼요. 전달된 쿼리에 푸시다운할 수 없기 때문이에요. 이 검사는 최상위 WHERE 조건자와 최상위 AND의 각 연결부를 다뤄요. 이 테이블 컬럼에 대한 PREWHERE는 이 설정의 대상이 아니에요: 이 테이블 엔진은 PREWHERE를 지원하지 않아서, 설정과 무관하게 그런 쿼리는 ILLEGAL_PREWHERE로 거부돼요. 검사는 필터를 푸시다운할 수 있는 경우에만 실행돼요: 이 테이블이 쿼리의 유일한 테이블이거나, INNER JOIN의 양쪽, 또는 외부 조인의 보존측(보존하는 쪽)(LEFT JOIN의 왼쪽, RIGHT JOIN의 오른쪽)일 때요. LEFT/RIGHT JOIN의 비보존측과 FULL JOIN의 양쪽에서는 아무것도 푸시다운되지도, 검사되기도 하지 않아요. 따라서 이 테이블 컬럼에 대한 필터는 엄격 모드에서도 조인 후 로컬로 적용돼요. 검사가 실행되는 곳에서 주변 쿼리에 조인된 다른 테이블을 참조하는 조건자는 푸시다운되지 않고 검사에서 제외돼요. 조인된 쪽만 참조하든, 하나의 AND가 아닌 표현식(예: OR) 안에서 이 테이블과 섞든 관계없이요. 그런 조건자는 평소 ClickHouse 평가 지점(조인 후의 WHERE, 그 앞의 PREWHERE)을 유지하고 거부되지 않아요.
복제본 (Replicas)
|로 나열해야 하는 여러 복제본을 지원해요. 예를 들어:
SELECT name FROM mysql(`mysql{1|2|3}:3306`, 'mysql_database', 'mysql_table', 'user', 'password');
또는
SELECT name FROM mysql(`mysql1:3306|mysql2:3306|mysql3:3306`, 'mysql_database', 'mysql_table', 'user', 'password');
반환값 (Returned value)
원래 MySQL 테이블과 같은 컬럼을 가진 테이블 객체예요.
MySQL의 일부 데이터 타입은 다른 ClickHouse 타입으로 매핑될 수 있어요 — 이는 쿼리 수준 설정 mysql_datatypes_support_level로 처리돼요.
INSERT 쿼리에서 테이블 함수 mysql(...)를 컬럼 이름 목록이 있는 테이블 이름과 구분하려면 FUNCTION 또는 TABLE FUNCTION 키워드를 사용해야 해요. 아래 예시를 참고하세요.
예시 (Examples)
MySQL의 테이블:
mysql> CREATE TABLE `test`.`test` (
-> `int_id` INT NOT NULL AUTO_INCREMENT,
-> `float` FLOAT NOT NULL,
-> PRIMARY KEY (`int_id`));
mysql> INSERT INTO test (`int_id`, `float`) VALUES (1,2);
mysql> SELECT * FROM test;
+--------+-------+
| int_id | float |
+--------+-------+
| 1 | 2 |
+--------+-------+
ClickHouse에서 데이터 선택:
SELECT * FROM mysql('localhost:3306', 'test', 'test', 'bayonet', '123');
또는 네임드 컬렉션 사용:
CREATE NAMED COLLECTION creds AS
host = 'localhost',
port = 3306,
database = 'test',
user = 'bayonet',
password = '123';
SELECT * FROM mysql(creds, table='test');
┌─int_id─┬─float─┐
│ 1 │ 2 │
└────────┴───────┘
enable_compression
MySQL 프로토콜 연결의 압축을 활성화해요.
기본값: false.
이 설정은 다음에 적용돼요:
mysql테이블 함수MySQL테이블 엔진MySQL데이터베이스 엔진- MySQL 통합에 사용되는 네임드 컬렉션
활성화하면 ClickHouse가 연결의 압축을 요청해요.
예시:
SELECT *
FROM mysql(
'mysql80:3306',
'clickhouse',
'test_table',
'root',
'password',
SETTINGS enable_compression = 1
);
대체 및 삽입 (Replacing and inserting):
INSERT INTO FUNCTION mysql('localhost:3306', 'test', 'test', 'bayonet', '123', 1) (int_id, float) VALUES (1, 3);
INSERT INTO TABLE FUNCTION mysql('localhost:3306', 'test', 'test', 'bayonet', '123', 0, 'UPDATE int_id = int_id + 1') (int_id, float) VALUES (1, 4);
SELECT * FROM mysql('localhost:3306', 'test', 'test', 'bayonet', '123');
┌─int_id─┬─float─┐
│ 1 │ 3 │
│ 2 │ 4 │
└────────┴───────┘
MySQL 테이블에서 ClickHouse 테이블로 데이터 복사:
CREATE TABLE mysql_copy
(
`id` UInt64,
`datetime` DateTime('UTC'),
`description` String,
)
ENGINE = MergeTree
ORDER BY (id,datetime);
INSERT INTO mysql_copy
SELECT * FROM mysql('host:port', 'database', 'table', 'user', 'password');
또는 최대 현재 id를 기준으로 MySQL에서 증분 배치만 복사하는 경우:
INSERT INTO mysql_copy
SELECT * FROM mysql('host:port', 'database', 'table', 'user', 'password')
WHERE id > (SELECT max(id) FROM mysql_copy);