MySQL Массив операторов SELECT & UPDATE на основе позиции индекса - PullRequest
1 голос
/ 10 марта 2020

Пожалуйста, посмотрите на изображение моей таблицы ниже, мои вопросы касаются выполнения UPDATE и SELECT в столбце sensor_values.

enter image description here

sensor_values столбец - это массив длиной 86 400, соответствующий значению датчика в каждую секунду дня. Сейчас я настроил его как тип данных JSON.

Мои вопросы

Как мне выполнить UPDATE для указанного индекса c?

  • т.е. Изменить 5-ую секунду дня или индекс [4] на значение 300.25

Как мне SELECT первые 300 секунд дня? псевдокод ниже

SELECT sensor_values[0:299] FROM facts WHERE d_date = '2020-03-10' AND dim_tag = 'Water_Temp'

Вот ссылка на DBFiddle для PostGresql, делающего что-то очень похожее на то, что я пытаюсь выполнить sh в MariaDB. https://dbfiddle.uk/?rdbms=postgres_12&fiddle=6999d2607c48a809ff995c8844c7f7bb

РЕДАКТИРОВАТЬ: общий обзор моей системы ниже

У меня есть Python конвейер данных, который читает значения тысяч датчиков и выполняет расчеты. Он отвечает за суммирование всех данных, хранящихся в других таблицах.

Мне нужны данные на втором уровне, чтобы они были легко доступны для анализа, что я пытаюсь сделать так, как об этом говорится в этой проблеме. , Моя мысль - получить второе число текущего дня в Python и использовать его в качестве индекса массива для обновления, как показано ниже:

now = datetime.datetime.now()
midnight = now.replace(hour=0, minute=0, second=0, microsecond=0)
secondsSinceMidnight = (now - midnight).seconds

sensorValue =  300.25
sensorTag = "Water_Temp"

sqlQuery = 
"""
UPDATE facts
SET sensor_values[%s] = %s
WHERE d_date = %s AND dim_tag = %s
"""
sqlValues = secondsSinceMidnight, sensorValue, datetime.datetime.today().strftime('%Y-%m-%d'), sensorTag

dbOps.update(sqlQuery, sqlValues)

Я не хочу отслеживать значения в Python в течение всего дня, а затем выполните INSERT, потому что в случае сбоя программы я потеряю все данные, а использование предварительно сформированного массива 1052 * позволит мне быстро программно определить, где отсутствуют данные в другие области моей программы (т.е. sensor_value - это 0 для набора секунд в дне).

Я использую термин предварительно сформированный массив , потому что я планирую периодически проверять свою программу на предмет наличия строки, доступной для каждого датчика на текущий и следующий день, обеспечивая плавные переходы в полночь, так как зерно очень мало.

Как и предполагалось в ответе Билла Карвина, это был мой первый подход - однако есть тысячи датчиков, и каждый из них будет публиковать каждую секунду. База данных будет расти в геометрической прогрессии: 1000 * 86400 = 86.4M строк вводится в день.

Таким образом, это не обязательно должно быть JSON, просто массив, модифицируемый в этом формате. Я думал, что это был правильный подход с MySQL. Обновлено название поста, чтобы лучше отражать проблему.

1 Ответ

2 голосов
/ 10 марта 2020

Если вы хотите использовать SQL для работы с отдельными элементами вашего набора значений датчиков, не храните его в JSON. Сохраните его как строки в обычной таблице.

CREATE TABLE facts (
 d_date DATE NOT NULL,
 second INT NOT NULL,
 dim_tag VARCHAR(...) NOT NULL,
 sensor_value NUMERIC(5,2) NOT NULL,
 PRIMARY KEY (d_date, second)
);

Тогда запросы, которые вы хотите сделать, более просты в SQL:

UPDATE facts SET sensor_value = 300.25 WHERE d_date = '2020-03-10' AND second = 4;

SELECT sensor_value FROM facts WHERE d_date = '2020-03-10' AND second < 300;

Если вы настаиваете на сохранении значений датчика как массив JSON, нет простого способа манипулирования отдельными элементами с использованием SQL. Вам нужно просто извлечь весь массив в ваше приложение, а затем распаковать JSON в массив, который вы можете прочитать или изменить с помощью кода.

Это слабое место использования JSON: вставлять коллекция значений в один столбец, и легко собрать всю коллекцию как одну единицу. Но довольно неловко, если вы хотите использовать SQL logi c для работы с отдельными элементами этой коллекции.

Может ли кто-нибудь опубликовать ответ, который даст вам результаты, которые вы запрашиваете в своем вопросе выше? Возможно, но разработка займет слишком много времени, и в следующий раз, когда вы захотите выполнить какую-либо другую задачу с этими данными, вам придется снова обратиться за помощью.

Использование JSON, когда вам действительно нужны дискретные элементы данных, не является устойчивым проектом, потому что это приводит к слишком высокому увеличению затрат на разработку программного обеспечения.


Дополнительная информация:

MySQL не поддерживает тип данных массива или любой синтаксис с использованием индексов массива, как вы предполагаете.

Я согласен, что 86,4 миллиона строк в день - это быстрый темп роста. Вы получите более 1 миллиарда строк менее чем за две недели.

Возможно, вам нужна база данных временных рядов вместо реляционной базы данных. Базы данных временных рядов оптимизируются для длинных потоков похожих данных и выполнения запросов агрегирования по столбцам. Они допускают быстрое поглощение этих потоков данных, а также хранят данные более компактно, чем ядро ​​базы данных, такое как InnoDB.

Вам следует взглянуть на один из них:

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...