zoukankan      html  css  js  c++  java
  • 使用mysql创建自己的物化视图

      物化视图,它是用于预先计算并保存表连接或聚集等耗时较多的操作的结果,这样,在执行查询时,就可以避免进行这些耗时的操作,从而快速的得到结果。物化视图有很多方面和索引很相似:使用物化视图的目的是为了提高查询性能;物化视图对应用透明,增加和删除物化视图不会影响应用程序中SQL 语句的正确性和有效性;物化视图需要占用存储空间;当基表发生变化时,物化视图也应当刷新

    创建自己的物化视图

    DROP TABLE sales_mv;
    CREATE TABLE sales_mv (
        product_name VARCHAR(128)  NOT NULL
      , price_sum    DECIMAL(10,2) NOT NULL
      , amount_sum   INT           NOT NULL
      , price_avg    FLOAT         NOT NULL
      , amount_avg   FLOAT         NOT NULL
      , sales_cnt    INT           NOT NULL
      , UNIQUE INDEX product (product_name)
    );
    
    INSERT INTO sales_mv
    SELECT product_name
        , SUM(product_price), SUM(product_amount)
        , AVG(product_price), AVG(product_amount)
        , COUNT(*)
      FROM sales
    GROUP BY product_name;

    当有需要时对物化视图进行刷新,存储过程如下

    DROP PROCEDURE refresh_mv_now;
    
    DELIMITER $$
    
    CREATE PROCEDURE refresh_mv_now (
        OUT rc INT
    )
    BEGIN
    
      TRUNCATE TABLE sales_mv;
    
      INSERT INTO sales_mv
      SELECT product_name
          , SUM(product_price), SUM(product_amount)
          , AVG(product_price), AVG(product_amount)
          , COUNT(*)
        FROM sales
      GROUP BY product_name;
    
      SET rc = 0;
    END;
    $$
    
    DELIMITER ;

    立刻刷新物化视图,当执行insert,delete和update时

    创建相关触发器

    DELIMITER $$
    
    CREATE TRIGGER sales_ins
    AFTER INSERT ON sales
    FOR EACH ROW
    BEGIN
    
      SET @old_price_sum = 0;
      SET @old_amount_sum = 0;
      SET @old_price_avg = 0;
      SET @old_amount_avg = 0;
      SET @old_sales_cnt = 0;
    
      SELECT IFNULL(price_sum, 0), IFNULL(amount_sum, 0), IFNULL(price_avg, 0)
           , IFNULL(amount_avg, 0), IFNULL(sales_cnt, 0)
        FROM sales_mv
       WHERE product_name = NEW.product_name
        INTO @old_price_sum, @old_amount_sum, @old_price_avg
           , @old_amount_avg, @old_sales_cnt
      ;
    
      SET @new_price_sum = @old_price_sum + NEW.product_price;
      SET @new_amount_sum = @old_amount_sum + NEW.product_amount;
      SET @new_sales_cnt = @old_sales_cnt + 1;
      SET @new_price_avg = @new_price_sum / @new_sales_cnt;
      SET @new_amount_avg = @new_amount_sum / @new_sales_cnt;
    
      REPLACE INTO sales_mv
      VALUES(NEW.product_name, @new_price_sum, @new_amount_sum, @new_price_avg
           , @new_amount_avg, @new_sales_cnt)
      ;
    
    END;
    $$
    
    DELIMITER ;
    DELIMITER $$
    
    CREATE TRIGGER sales_del
    AFTER DELETE ON sales
    FOR EACH ROW
    BEGIN
    
      SET @old_price_sum = 0;
      SET @old_amount_sum = 0;
      SET @old_price_avg = 0;
      SET @old_amount_avg = 0;
      SET @old_sales_cnt = 0;
    
      SELECT IFNULL(price_sum, 0), IFNULL(amount_sum, 0), IFNULL(price_avg, 0)
           , IFNULL(amount_avg, 0), IFNULL(sales_cnt, 0)
        FROM sales_mv
       WHERE product_name = OLD.product_name
        INTO @old_price_sum, @old_amount_sum, @old_price_avg
           , @old_amount_avg, @old_sales_cnt
      ;
    
      SET @new_price_sum = @old_price_sum - OLD.product_price;
      SET @new_amount_sum = @old_amount_sum - OLD.product_amount;
      SET @new_price_avg = @new_price_sum / @new_amount_sum;
      SET @new_sales_cnt = @old_sales_cnt - 1;
      SET @new_amount_avg = @new_amount_sum / @new_sales_cnt;
    
      REPLACE INTO sales_mv
      VALUES(OLD.product_name, @new_price_sum, @new_amount_sum
           , IFNULL(@new_price_avg, 0), IFNULL(@new_amount_avg, 0)
           , @new_sales_cnt)
      ;
    
    END;
    $$
    
    DELIMITER ;
    DELIMITER $$
    
    CREATE TRIGGER sales_upd
    AFTER UPDATE ON sales
    FOR EACH ROW
    BEGIN
    
      SET @old_price_sum = 0;
      SET @old_amount_sum = 0;
      SET @old_price_avg = 0;
      SET @old_amount_avg = 0;
      SET @old_sales_cnt = 0;
    
      SELECT IFNULL(price_sum, 0), IFNULL(amount_sum, 0), IFNULL(price_avg, 0)
           , IFNULL(amount_avg, 0), IFNULL(sales_cnt, 0)
        FROM sales_mv
       WHERE product_name = OLD.product_name
        INTO @old_price_sum, @old_amount_sum, @old_price_avg
           , @old_amount_avg, @old_sales_cnt
      ;
    
      SET @new_price_sum = @old_price_sum + (NEW.product_price - OLD.product_price);
      SET @new_amount_sum = @old_amount_sum + (NEW.product_amount
                          - OLD.product_amount);
      SET @new_sales_cnt = @old_sales_cnt;
      SET @new_price_avg = @new_price_sum / @new_sales_count;
      SET @new_amount_avg = @new_amount_sum / @new_sales_cnt;
    
      REPLACE INTO sales_mv
      VALUES(OLD.product_name, @new_price_sum, @new_amount_sum
           , IFNULL(@new_price_avg, 0), IFNULL(@new_amount_avg, 0)
           , @new_sales_cnt)
      ;
    
    END;
    $$
    
    DELIMITER ;

    参考:http://www.fromdual.com/mysql-materialized-views#implement

  • 相关阅读:
    Javascript的实例化与继承:请停止使用new关键字
    关于Unicode和URL encoding入门的一切以及注意事项
    Javascript: 从prototype漫谈到继承(2)
    你真的了解setTimeout和setInterval吗?
    javascript同步分页
    jquery ui dialog去除第一个文本框焦点问题
    指定范围内的随机数
    Mac下的mysql初始密码如何重置?
    进度条插件
    浏览器事件以及事件代理
  • 原文地址:https://www.cnblogs.com/phpfans/p/3154586.html
Copyright © 2011-2022 走看看