2017-01-11 3 views
0

샘플 데이터에서 memsql 성능 테스트를 실행 중이며 JSON 데이터를 쿼리하는 동안 동작이 매우 좋지 않습니다. 2 개의 테이블이 매우 유사하고 똑같은 정보 (동일한 csv 파일에서로드 됨)를 포함합니다. 차이점은 segments 열이 JSON 대 varchar (255)입니다. MemSQL 검색 성능 : JSON vs varchar

memsql> select * from test_events limit 1; 
+---------------------+---------+------------------------+ 
| timestamp   | user_id | segments    | 
+---------------------+---------+------------------------+ 
| 2017-01-04 00:00:00 | 26834 | [19,18,9,6,7,22,34,43] | 
+---------------------+---------+------------------------+ 

아래는 동일한 정보를 페치 2 개 쿼리이지만 속도가 상이하다 :
CREATE TABLE `test_events` (
`timestamp` datetime NOT NULL, 
`user_id` int(20) NOT NULL, 
`segments` JSON COLLATE utf8_bin NOT NULL, 
KEY `timestamp` (`timestamp`) /*!90619 USING CLUSTERED COLUMNSTORE */, 
/*!90618 SHARD */ KEY `user_id` (`user_id`) 


CREATE TABLE `test_events_string` (
`timestamp` datetime NOT NULL, 
`user_id` int(20) NOT NULL, 
`segments` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '', 
KEY `timestamp` (`timestamp`) /*!90619 USING CLUSTERED COLUMNSTORE */, 
/*!90618 SHARD */ KEY `user_id` (`user_id`) 

및 예컨대 데이터가 (배열의 항목 양은 1 내지 20에 따라 다름). 두 쿼리가 두 번 실행되었고 두 번째 실행이 복사되었습니다.

memsql> select count(*) from test_events where json_array_contains_double(segments, 42); 
+----------+ 
| count(*) | 
+----------+ 
| 79312103 | 
+----------+ 
1 row in set (15.86 sec) 

memsql> select count(*) from test_events_string where segments like '%42%'; 
+----------+ 
| count(*) | 
+----------+ 
| 79312103 | 
+----------+ 
1 row in set (1.96 sec) 

memsql> select count(*) from test_events; 
+-----------+ 
| count(*) | 
+-----------+ 
| 306939340 | 
+-----------+ 
1 row in set (0.02 sec) 

그래서 JSON 검색은 % x % LIKE보다 8 배 느립니다. 그것을 향상시킬 수있는 것이 있습니까?

다른 접근 방식으로 비즈니스 논리 문제를 해결하는 방법을 조언 할 수 있을까요? 기본적으로 우리는 사용자 및 이벤트에 대한 이벤트를 기록하고 일부 엔티티의 ID 배열을 첨부합니다. 이 배열은 사용자의 라이프 사이클 동안 자주 변경됩니다. 위 예제와 거의 같은 1 또는 여러 ID로 필터링 된 쿼리를 실행하고 싶습니다.

경우에 따라 일부 기술 사양이 적용됩니다. 3 개의 동일한 베어 메탈 서버. 1 서버는 애그리 게이터 용이고 2 서버용입니다. 각 시스템에는 NUMA가 있으므로 총 4 개의 리프 노드가 있습니다. 빠른 SSD, 32Cores (2 X [email protected]), 32GB RAM.

답변

1

나는 이것이 천천히한다는 사실에 놀라지 않습니다. MemSQL은 원주 형 json에 대해 쪽모 세공 기반 압축을 사용합니다. 우리는 이러한 종류의 빠른 검색을 아직하지 못했습니다 (그러나 계속 지켜봐주십시오!).

몇 가지 옵션이 있습니다. 하나는 42를 항상 검색하려는 경우 지속 열 (https://docs.memsql.com/docs/persistent-computed-columns)을 사용할 수 있습니다. 유스 케이스가 아닌 것 같습니다.

다른 옵션은 항상 동일한 배열을보고있는 경우 표준화 된 테이블 (https://en.wikipedia.org/wiki/Database_normalization)을 만들 수 있다는 것입니다.
과 비슷합니다. create table test_events_array (timestamp datetime not null, user_id bigint not null, segment bigint, shard(user_id), key(ts) using clustered columnstore) 그러면 select count(*) from test_events_array where segment=42 번개가 빠릅니다.

또한이 스키마로 거의 아무 것도 압축하지 않습니다.