1

我在处理数据库中的大数据时遇到以下问题:

基本上,来自数字传感器的所有计量每秒都存储在数据库中。报告应该从所有数据中显示的只是发生的变化,例如在时间 X 寄存器 #1 将值从 0 更改为 1。

我创建了一个程序,它只能返回我需要的数据(更改),这为我节省了大量的 php 处理但最大的问题是,对于 4 天的当前数据,查询需要 6 * N秒完成其中 N 是所选寄存器的数量。

现在我想知道克服这个问题的最佳解决方案是什么。

另一个想法是在数据计量的每个新插入上触发,但问题是这将更加复杂,因为我需要查看在另一个时间提交的先前计量。

所以我想创建在新数据以某种方式到达时会自动更新的视图。这意味着当对报告发出请求时,数据将准备好并从视图中获取。

这会是一个好的解决方案吗?

4

2 回答 2

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 或其他东西来运行查询,该查询会将您的数据摘要创建到一个小得多的表格中,您的报告将用于该表格。

于 2012-09-14T10:10:45.383 回答
0

使用单个查询就可以从现有数据中识别状态更改,但是(正如您所发现的)非常昂贵。我会敦促您将每个状态更改存储在缓存中。

正如@Fluffeh 解释的那样,如果您使用合适的索引,从现有表中查找最新状态不会很昂贵;所以触发方法应该是相当合理的。

所以:

  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. 从有权修改新表的用户定义触发器:

    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
           )
    ;
    
于 2012-09-14T11:06:44.790 回答