2012-09-14 6 views
1

I 데이터베이스 큰 데이터 처리를 다음과 같은 문제가 오전 : MySQL의 대용량 데이터 조작 처리

기본적 디지털 센서로부터의 모든 측정은 각 초 동안 데이터베이스에 저장한다. 모든 데이터에서 보고서가 표시해야하는 것은 예를 들어 시간 X에서 레지스터 # 1이 값을 0에서 1로 변경 한 경우와 같은 변경 사항뿐입니다.

데이터 i 만 반환 할 수있는 프로 시저를 만들었습니다 필요 (변경), 그리고 PHP에서 많은 처리를 절약하지만 큰 문제는 4 일의 현재 데이터에 대해 쿼리 N * 선택한 레지스터의 수를 완료하는 데 6 * N 초 걸리는 것입니다.

이제이 문제를 극복하기위한 최상의 솔루션이 무엇인지 궁금합니다.

또 다른 생각은 데이터 미터링을 새로 삽입 할 때마다 트리거를 만드는 것입니다. 그러나 문제는 다른 시간에 제출 된 이전 미터링을 조사해야하기 때문에 더 복잡 할 것이라는 점입니다.

그래서 어떤 식 으로든 새로운 데이터가 도착하면 자동으로 업데이트 될 뷰를 생성 할 생각입니다. 즉, 보고서에 대한 요청이있을 때 데이터가 준비되고 뷰에서 가져올 수 있습니다.

좋은 해결책이 될까요?

답변

0

기존 데이터의 상태 변화를 단일 쿼리로 확인할 수는 있지만 매우 비쌉니다. 각 상태 변경 사항을 캐시에 저장하도록 권하고 싶습니다.

@Fluffeh explained과 같이 적절한 색인을 사용하면 기존 테이블에서 최신 상태를 찾는 것이 그리 비싸지는 않을 것입니다. 방아쇠 접근법은 상당히 합리적이어야합니다.

그러므로 (이미 존재하지 않는 경우)

  1. 은 적절한 인덱스를 정의

    ALTER TABLE existing_table ADD INDEX (register_id, timestamp); 
    
  2. 가 캐시 테이블을 생성 (및 임의로 설정된 사용자 권한이 없다 할 수 있도록 응용 프로그램에서 직접 수정 가능) :

    CREATE TABLE status_changes VALUES (
        register_id ..., 
        timestamp TIMESTAMP, 
        old_status ..., 
        new_status ..., 
    
        PRIMARY KEY    (register_id, timestamp), 
    
        FOREIGN KEY    (register_id, timestamp, old_status) 
        REFERENCES existing_table (register_id, timestamp, status), 
    
        FOREIGN KEY    (register_id, timestamp, new_status) 
        REFERENCES existing_table (register_id, timestamp, status) 
    ); 
    
  3. Define

    DELIMITER ;; 
    
    CREATE TRIGGER record_change AFTER INSERT ON existing_table FOR EACH ROW 
    BEGIN 
        DECLARE _last_status ... ; 
    
        SELECT last.status 
        INTO  _last_status 
        FROM  existing_table AS last 
        WHERE last.register_id <=> NEW.register_id 
         AND last.timestamp < NEW.timestamp 
        ORDER BY last.timestamp DESC 
        LIMIT 1; 
    
        IF NOT NEW.status <=> _last_status THEN 
        INSERT INTO status_changes (
         register_id, 
         timestamp, 
         old_status, 
         new_status 
        ) VALUES (
         NEW.register_id, 
         NEW.timestamp, 
         _last_status, 
         NEW.status 
        ); 
        END IF; 
    END;; 
    
    DELIMITER ; 
    
  4. 은 기록 데이터에서 새 테이블을 채 웁니다 : 새 테이블 수정할 수있는 권한이있는 사용자로부터 트리거 불행하게도

    INSERT IGNORE INTO status_changes (
        register_id, 
        timestamp, 
        old_status, 
        new_status 
    ) 
    SELECT NEW.register_id, 
         NEW.timestamp, 
         (
         SELECT last.status 
         FROM  existing_table AS last 
         WHERE last.register_id <=> NEW.register_id 
           AND last.timestamp < NEW.timestamp 
         ORDER BY last.timestamp DESC 
         LIMIT 1 
         ) AS _last_status, 
         NEW.status 
    FROM existing_table AS NEW 
    WHERE NOT NEW.status <=> (
         SELECT last.status 
         FROM  existing_table AS last 
         WHERE last.register_id <=> NEW.register_id 
           AND last.timestamp < NEW.timestamp 
         ORDER BY last.timestamp DESC 
         LIMIT 1 
         ) 
    ; 
    
+0

죄송합니다. 마지막 질문은 무엇입니까? 임씨는 현재 테이블에 삽입 할 때마다 상태가 변경되도록 작업하고 있습니다. 저 시간에 일정 기간 동안 각 레지스터의 상태를 변경하는 것만으로도 충분할 것입니다. –

+0

@GeorgeNikolaides : 새로운 테이블을 채우려는 역사적인 데이터로 가득 찬 데이터베이스가 있다고 가정 했습니까? 4 단계에서 (일회성 운동으로) 모든 것이 후속/새 데이터에 대해 트리거가됩니다. – eggyal

+0

실제로 데이터베이스는 매 초마다 새로운 계량 (센서 값 - 0과 1)으로 채워지고, 지금 당신이하는 일은 새로운 테이블에서 0과 1의 변화를 모니터링하는 것입니다. 보고서 및 추세 검색 시간이 늘어납니다. –

0

귀하의 테이블이 멋지게 색인이 생성되었으며 귀하의 검색어가 이러한 색인을 잘 사용한다고 가정합니다.

이 경우 잠재적으로 복합 색인에서 많은 이익을 얻는 것처럼 보입니다 (날짜와 등록자 모두에서 하나씩). 각각에 대한 색인이 도움이되지만, 둘 모두에 대한 복합 색인이 훨씬 도움이 될 것입니다.

구문

는 종합 지수는 추가 : 당신이에 볼 수 있었다

alter table yourTableName add index yourIndexName(col1, col2); 

mysql> select * from table1; 

+---------+------+------+-------------+ 
| autonum | ID | name | metavalue | 
+---------+------+------+-------------+ 
|  1 | 1 | Rose | Drinker  | 
|  2 | 1 | Rose | Nice Person | 
|  3 | 1 | Rose | Runner  | 
|  4 | 2 | Gary | Player  | 
|  5 | 2 | Gary | Funny  | 
|  6 | 2 | Gary | NULL  | 
|  7 | 2 | Gary | Smelly  | 
+---------+------+------+-------------+ 
7 rows in set (0.01 sec) 

mysql> alter table table1 add index autoNumID(autonum, ID); 
Query OK, 0 rows affected (0.02 sec) 
Records: 0 Duplicates: 0 Warnings: 0 

다른 것은 한 (시간당 또는 하루 등 당) 업데이트되는 요약 테이블을하고있다. 크론 (CRON) 또는 다른 것을 사용하여 쿼리를 실행하면 훨씬 작은 테이블에 데이터 요약이 만들어져보고가 제대로 작동합니다.

+0

내가 어떤 인덱스를 사용하지 않는, 그리고 난 생각 이것이 가장 큰 문제라고. 값은 2 진 값 (0과 1)에서 하나의 십진 값으로 변환됩니다. 데이터베이스에서 매초마다 저장되는 것은 10 진수 값이라는 것을 의미합니다. 즉, 데이터를 가져올 때마다 다음과 같이해야합니다. SUBSTRING (역 (LPAD (BIN (DiValue)), 16, 0)) FROM 'alias_offset'FOR 1) –

+0

* 땅 * 오, 안녕하세요 세상에 배트맨, 우리는 승자가 있다고 생각합니다. – Fluffeh

+0

내부 조인이 없다면, 당신이 말하는 것입니다. –