2009-08-19 3 views
1

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

Простой пример:

Timestamp ID 
    1  A 
    1  B 
    2  A 
    2  B 
    2  C 
    3  A 
    3  D 
    4  D 
    4  E 

В этом случае, Пункт С получает создан где-то между снимком 1 и 2, и где-то между снимком 2 и 3 В и С исчезают и D получает созданный и т.д.

Таблица достаточно велика (миллионы записей), и для каждой отметки времени около 50 записей.

Каков наиболее эффективный способ выбора идентификаторов предметов для предметов, которые исчезают между двумя последовательными отметками времени?

Таким образом, для приведенного выше примера ...
между 1 и 2: NULL
между 2 и 3: B, C
Между 3 и 4: А

Если это не делает запрос неэффективен, может ли он быть расширен, чтобы автоматически использовать последнюю (т.е. MAX) временную метку и предыдущую?

+0

Интересный вопрос. Я думаю, что я сделаю из него сообщение в блоге. – Quassnoi

ответ

1

Update:

Посмотреть эту запись в моем блоге подробности производительности:

SELECT ts, 
     (
     SELECT GROUP_CONCAT(id) 
     FROM mytable mi 
     WHERE mi.ts = 
       (
       SELECT MAX(ts) 
       FROM mytable mp 
       WHERE mp.ts = mo.pts 
       ) 
       AND NOT EXISTS 
       (
       SELECT NULL 
       FROM mytable mn 
       WHERE mn.ts = mo.ts 
         AND mn.id = mi.id 
       ) 
     ) 
FROM (
     SELECT @r AS pts, 
       @r := ts AS ts 
     FROM (
       SELECT @r := NULL 
       ) vars, 
       (
       SELECT DISTINCT ts 
       FROM mytable 
       ) moo 
     ) mo 

Чтобы выбрать только последнее изменение:

SELECT ts, 
     (
     SELECT GROUP_CONCAT(id) 
     FROM mytable mi 
     WHERE mi.ts = 
       (
       SELECT MAX(ts) 
       FROM mytable mp 
       WHERE mp.ts < mo.ts 
       ) 
       AND NOT EXISTS 
       (
       SELECT NULL 
       FROM mytable mn 
       WHERE mn.ts = mo.ts 
         AND mn.id = mi.id 
       ) 
     ) 
FROM (
     SELECT MAX(ts) AS ts 
     FROM mytable 
     ) mo 

Для этого, чтобы быть эффективным, вы должны иметь составной индекс по mytable (timestamp, id) (в таком порядке).

1

Другим способом просмотра этого является то, что вы хотите найти записи, которые существуют в отметке времени 1, которые не существуют в метке времени # 2. Самый простой способ?

SELECT Timestamp 
FROM records AS t1 
WHERE NOT EXISTS (SELECT 1 FROM records AS t2 WHERE t2.id = t1.id AND t2.Timestamp = t1.Timestamp + 1) 

Конечно, я здесь эксплуатирую тот факт, что ваш пример метка время целые числа, когда на самом деле я полагаю, что они являются подлинными метками времени. Но оказывается, что целые числа работают так хорошо для этой конкретной цели, им было бы очень удобно иметь дело. Поэтому, возможно, нам следует составить нумерованный список всех доступных временных меток. Самый простой способ получить , что?

CREATE TEMPORARY TABLE timestamp_map AS (
    timestamp_id AS INT UNSIGNED AUTO_INCREMENT PRIMARY KEY, 
    timestamp_value AS DATETIME 
); 

INSERT INTO timestamp_map (timestamp_value) (SELECT DISTINCT timestamp FROM records ORDER BY timestamp); 

(Вы можете также сохранить такую ​​таблицу, постоянно с использованием триггеров.)

Это немного там, но я получил подобные методы, чтобы работать очень эффективно в прошлом для данных, как то, что вы описываете, когда много подзапросов назад и вперед и NOT EXISTS оказались слишком медленными.

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