2013-05-08 3 views
0

센서, 판독 값 및 판독 값을 나타내는 시간 스탬프를 나타내는 측정 값 데이터베이스가 있습니다. 측정 값은 변경 사항이있을 때만 기록됩니다. 각 센서가 특정 측정 값을 읽는 범위를 보여주는 결과 세트를 생성하려고합니다.MySQL - 데이터 포인트를 범위로 바꾸기

타임 스탬프는 밀리 초 단위이지만 결과는 몇 초 만에 출력됩니다. 내가 서브 쿼리를 사용하여 원하는 결과를 얻고 지금

CREATE TABLE `raw_metric` (
    `row_id` BIGINT NOT NULL AUTO_INCREMENT, 
    `sensor_id` BINARY(6) NOT NULL, 
    `timestamp` BIGINT NOT NULL, 
    `angle` FLOAT NOT NULL, 
    PRIMARY KEY (`row_id`) 
) 

하지만 데이터 포인트를 많이있을 때 그것은 매우 느린입니다 : 여기

는 테이블의

SELECT row_id, 
    HEX(sensor_id), 
    angle, 
    (
     COALESCE((
       SELECT MIN(`timestamp`) 
       FROM raw_metric AS rm2 
       WHERE rm2.`timestamp` > rm1.`timestamp` 
        AND rm2.sensor_id = rm1.sensor_id 
       ), UNIX_TIMESTAMP() * 1000) - `timestamp` 
     )/1000 AS duration 
FROM raw_metric AS rm1 

는 본질적으로 , 범위를 얻으려면, 나는 다음 독서를 얻을 필요가있다 (또는 다른 독서가 없으면 현재 시간을 사용한다). 부속 조회는 현재 시간보다 늦지 만 동일한 센서의 최소 시간 소인을 찾습니다.

이 쿼리는 자주 발생하지 않으므로 타임 스탬프 열에 인덱스를 추가하고 삽입 속도를 늦출 필요가 없습니다. 나는 누군가가 이것을하는 대안적인 방법에 대한 제안을 가지기를 바랬다.

UPDATE : ROW_ID의 타임 스탬프와 함께 증가해야하지만이 때문에 네트워크 지연 문제로 보장 할 수 없습니다. 따라서 row_id가 낮은 항목이 나중에 row_id 이후에 발생하는 것은 가능하지만 가능성은 없습니다.

+0

이 하위 쿼리의 성능을 향상시키는 적절한 방법은 raw_metric (sensor_id, timestamp)에 인덱스를 지정하는 것입니다. 색인을 추가하고 삽입의 성능을 테스트하는 것이 좋습니다. –

+0

@GordonLinoff 예, 이것은 하위 쿼리를 향상시키는 가장 좋은 방법이 될 수 있지만 하위 쿼리를 사용하지 않고이 작업을 수행하는 다른 방법이 있습니까? –

+0

@GordonLinoff 타임 스탬프가 색인 된 raw_metric의 임시 테이블을 만드는 것은 어떻습니까? –

답변

0

기본 키에 auto_increment를 사용하는 경우 쿼리 조건 부분에서 timestamp를 row_id로 바꿀 수 있습니다. 좋아요 :

SELECT row_id, 
HEX(sensor_id), 
angle, 
(
    COALESCE((
      SELECT MIN(`timestamp`) 
      FROM raw_metric AS rm2 
      WHERE rm2.`row_id` > rm1.`row_id` 
       AND rm2.sensor_id = rm1.sensor_id 
      ), UNIX_TIMESTAMP() * 1000) - `timestamp` 
    )/1000 AS duration 
FROM raw_metric AS rm1 

빨리 처리해야합니다.

새 감지기 값의 빠른 선택 행 ID에 대해 하나 이상의 하위 쿼리를 추가 할 수도 있습니다. 이것은 솔루션으로보다 주석으로 아마 더 적합

SELECT row_id, 
HEX(sensor_id), 
angle, 
(
    COALESCE((
     SELECT timestamp FROM raw_metric AS rm1a 
     WHERE row_id = 
     (
      SELECT MIN(`row_id`) 
      FROM raw_metric AS rm2 
      WHERE rm2.`row_id` > rm1.`row_id` 
       AND rm2.sensor_id = rm1.sensor_id 
     ) 
     ), UNIX_TIMESTAMP() * 1000) - `timestamp` 
    )/1000 AS duration 
FROM raw_metric AS rm1 
+0

업데이트를 추가했습니다 ... 그 row_id가 그렇게 될 것이라고 보장 할 수 없습니다. –

0
Select rm1.row_id 
     ,HEX(rm1.sensor_id) 
     ,rm1.angle 
     ,(COALESCE(rm2.timestamp, UNIX_TIMESTAMP() * 1000) - rm1.timestamp) as duration 
from raw_metric rm1 
left outer join 
     raw_metric rm2 
on  rm2.sensor_id = rm1.sensor_id 
and  rm2.timestamp = (
      select min(timestamp) 
      from raw_metric rm3 
      where rm3.sensor_id = rm1.sensor_id 
      and rm3.timestamp > rm1.timestamp 
      ) 
+0

이것이 개선 된 방법을 잘 모르겠다. 이 작업은 여전히 ​​동일한 하위 쿼리를 수행하지 않지만 지금은 조인을 추가하고 있습니까? –

1

하지만 주석 너무 깁니다 참조하십시오.

lead() 함수를 MySQL에 구현하려고하고 있으며, MySQL은 불행히도 창 함수를 가지고 있지 않습니다. Oracle, DB2, Postgres, SQL Server 2012로 전환하고 거기에 내장 (및 최적화) 된 기능을 사용할 수 있습니다. 좋아, 현실적이지 않을 수도있다.

데이터 구조가 주어지면 상관 하위 쿼리 또는 비 equijoin (실제로는 sensor_id에 일치하므로 부분 동등 조인)을 수행해야합니다. 색인을 추가하지 않으면 이러한 작업이 고비용이 될 수 있습니다. 초당 수십 번 측정을 추가하지 않는 한, 색인에 대한 추가 오버 헤드는 큰 문제가되지 않습니다.

데이터 구조를 변경할 수도 있습니다. 판독 값을 열거하는 일련 번호 인 "센서 카운터"가있는 경우,이를 성능 향상을 위해 여전히 색인을 원할 수도 있지만 equijoin으로 사용할 수 있습니다. 이것을 테이블에 추가하는 것은 트리거가 필요하며 삽입 할 때의 인덱스보다 더 나쁠 수 있습니다.

소수의 센서 만있는 경우 각각에 대해 별도의 테이블을 만들 수 있습니다. 오, 나는이 제안에 신음 소리를 느낄 수있다. 하지만 그렇게했다면 자동으로 증가하는 ID는 동일한 역할을 수행합니다. 솔직하게 말해서, 각 손에 센서의 수를 세지 만하면됩니다.

결국 삽입하는 동안 적중을 취하고 각 레코드에 "유효"및 "종료"시간 (센서 ID와 타임 스탬프 또는 ID 인덱스)을 추가하는 것이 좋습니다. 테이블에 더 많은 용도가있을 것입니다.

하나의 센서에 대해이 작업을 수행하는 경우 정보에 대한 임시 테이블을 만들고 자동 증가 된 ID 열을 사용하여 데이터를 삽입하십시오.

insert into temp_rawmetric (orig_row_id, sensor_id, timestamp, angle) 
    select orig_row_id, sensor_id, timestamp, angle 
    from raw_metric 
    order by sensor_id, timestamp; 

테이블 자동 증가 및 기본 키입니다 temp_rawmetric_id 열이 있는지 확인은 (AN 산업사를 생성 ex 자동으로). order by은 타임 스탬프에 따라이 값이 증가되도록합니다.

select trm.sensor_id, trm.angle, 
     trm.timestamp as startTime, trmnext.timestamp as endTime 
from temp_rawmetric trm left outer join 
    temp_rawmetric trmnext 
    on trmnext.temp_rawmetric_id = trm.temp_rawmetric_id+1; 

이 추가로 데이터를 원본 데이터를 통해 패스를 필요로하고 기본 키는 임시 테이블에 조인으로

그런 다음 당신은 당신의 쿼리를 할 수 있습니다. 처음에는 약간의 시간이 걸릴 수 있습니다. 두 번째는 꽤 빠르다.

+0

마지막 단락까지 여러분을 따라갔습니다 ...이 추가 열은 정확히 무엇입니까? –

+0

마지막 코드 예제에서 "trmnext"가 "trm2"라고 가정했습니다. 나는 당신의 단락에서 여전히 혼란 스럽다. "삽입하는 동안 히트를 치고 각 레코드에"효과적 "및"끝 "시간을 ...이 추가 열을 사용하면 테이블에 대한 더 많은 용도가 발견 될 것입니다. 'raw_metric'에 삽입 할 때 값을 삽입하는 테이블의 추가 열에 대해? –