MemSQL搜索性能:JSON vs varchar

时间:2017-01-11 15:09:01

标签: performance memsql

我正在对示例数据运行一些memsql性能测试,并且在查询JSON数据时行为很差。 我有2个表非常相似,包含完全相同的信息(从相同的csv文件加载)。不同之处在于segments列是JSON与varchar(255)。

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 * 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个获取相同信息的查询,但速度不同。两个查询都已执行两次,我复制第二次运行:

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,32核(2 X E5-2650v2@2.60GHz),32GB RAM。

1 个答案:

答案 0 :(得分: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将会闪电般快速。

它可能也会用该模式压缩到几乎为零。

相关问题