Я выполняю некоторые тесты производительности memsql на выборочных данных и имею очень плохое поведение при запросе данных JSON. У меня есть 2 таблицы, которые выглядят очень похожими и содержат точно такую же информацию (загружается из одного и того же файла csv). Разница в том, что столбец segments
является JSON vs varchar (255).Производительность поиска в MemSQL: JSON vs varchar
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 запросы, которые начнут извлекать ту же информацию, но скорость отличается. Оба запроса были выполнены дважды, и я копирую 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 в 8 раз медленнее, чем% х% LIKE. Есть ли что-то, что может улучшить его?
Возможно, вы можете посоветовать, как решить эту проблему бизнес-логики с помощью другого подхода? В принципе, мы регистрируем события для пользователей и для каждого события, которое мы хотим связать с массивом идентификаторов некоторых объектов. Этот массив часто изменяется в течение жизненного цикла пользователя. Мы хотим запустить фильтрацию запросов с помощью 1 или многих идентификаторов, что очень похоже на пример выше.
На всякий случай некоторые технические характеристики. 3 идентичных сервера с голой металликой. 1 для агрегатора, 2 для данных. У каждой машины есть NUMA, поэтому всего 4 листа. Быстрые SSD, 32Cores (2 X [email protected]), 32 ГБ оперативной памяти.