2012-06-11 1 views
1

Моя таблица имеет следующие поля:SQL-вставка строки, если поле изменилось (высокая производительность)

SENSOR_ID INTEGER, 
SENSOR_READING REAL, 
TIME_OF_READING TIMESTAMP, 
HASCHANGED BOOLEAN 

Каждый датчик срабатывает> 10'000 показания/день. Я хочу регистрировать только те данные, где SENSOR_READING отличается от последнего зарегистрированного значения.

В качестве альтернативы, я могу зарегистрировать все, кроме HASCHANGED, чтобы true, когда SENSOR_READING отличается от последнего зарегистрированного значения.

Что является наиболее сильным синтаксисом для выполнения этого (с PostgreSQL, без php-логики)?

+0

вы не должны использовать 'REAL', если вам нужны точные показания. Вместо этого вы должны использовать 'NUMERIC'. –

+0

Почему бы не сохранить последнее чтение в памяти вашего приложения, которое контролирует датчик и только регистрируется в базе данных, если оно изменяется. –

+1

С ограничением 'UNIQUE' вы не можете регистрировать все показания. Если вы хотите только иметь последнее чтение. Это так? –

ответ

1

Вы могли бы сделать что-то вроде этого

insert into readings (sensor_id, sensor_reading, time_of_reading) 
select 42, 1234.5678, current_timestamp 
from readings 
where not exists (select * 
        from readings 
        where sensor_reading = 1234.5678 
        and time_of_reading = (select max(time_of_reading) 
              from readings 
              where sensor_id = 42); 

Это потребует sensor_reading столбец индексироваться, но я до сих пор сомневаюсь, что это на самом деле будет быстрее.

Вам не нужно хранить атрибут haschanged, потому что вы можете рассчитывать, что при получении данных:

select sensor_id, 
     sensor_reading, 
     time_of_reading, 
     lag(sensor_reading) over (partition by sensor_id order by time_of_reading) = sensor_reading as has_changed 
from readings; 

Это предполагает, что sensor_id не на самом деле уникален, иначе вы не могли бы хранить более одного чтение для датчика

далее предполагается, что вы изменить что REAL столбца в NUMERIC колонки, поскольку REAL значение с использованием = не является точным (на самом деле хранение не является точным, чтобы начать с)

+0

Что делать, если показания датчика соответствуют более старому (не последнему) чтению? FWIW, я думаю, его дизайн схемы сильно сломан. – Bohemian

+0

@Bohemian: хорошая точка. Думаю, идея Юджина пока лучшая. –

+0

@a_horse, я бы предпочел ваше предложение, потому что он не требует дополнительной таблицы. Я попробую, а также Юджина, и отчитаюсь. Большое спасибо всем вам! – aag

1

Я полагаю, что вам нужно добавить столбец, где разместить последнее значение, а затем при каждом «чтении» вы можете провести сравнение между этими двумя столбцами.

Это подход «чистого sql», но есть решение гораздо лучше, например обратный вызов (вы сказали о php, поэтому я предлагаю symfony и doctrine, которые могут сделать это для вас, и это действительный подход, если вам нужно сделать некоторые шаг, если значения изменены или что-то вроде этого ...)

2

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

+0

+1, Очень хорошая идея –

+0

Отличное предложение, большое спасибо. Я не могу проголосовать за тебя, потому что я новичок, и я еще не получил право на это! – aag

+0

Также добавьте триггер «на вставку» на событие датчика. Это можно использовать для подачи новых сенсоров в таблицу «рецептор», как только они появятся впервые. (на самом деле, это «вверх» к таблице «рецепторов») – wildplasser

Смежные вопросы