是否可以对视图进行分区,如MySQL中的表格?

时间:2016-07-05 14:15:40

标签: mysql view database-partitioning

我已经从大约10个表的UNION ALL子句创建了视图,并希望按日期范围应用一些搜索查询。但随着记录数量的增加,执行查询需要更长的时间。现在该视图有20亿行。

表结构如下:

CREATE TABLE IF NOT EXISTS `tbl_queue_stats_0716` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `server_id` int(11) NOT NULL, 
    `uniqueid` varchar(100) DEFAULT NULL, 
    `queue_datetime` datetime NOT NULL, 
    `queue_timestamp` varchar(100) NULL, 
    `qname_id` int(11) NOT NULL, 
    `qagent_id` int(11) NOT NULL, 
    `qevent_id` int(11) NOT NULL, 
    `info1` varchar(100) DEFAULT NULL, 
    `info2` varchar(100) DEFAULT NULL, 
    `info3` varchar(100) DEFAULT NULL, 
    `info4` varchar(100) DEFAULT NULL, 
    `info5` varchar(100) DEFAULT NULL, 
    PRIMARY KEY (`id`)
);

表是按月创建的,因此可以有tbl_queue_stats_0616,tbl_queue_stats_0516,tbl_queue_stats_0416等表格。

如果需要搜索2个月或更长时间的日期范围,我想在多个表格上应用搜索查询。

搜索查询如下所示:

select  server_id,server_name,queue_id,queue_name,qevent_id,event,
        count(id) as cnt,sum(info1) as info1, sum(info2) as info2,
        sum(info3) as info3, sum(info4) as info4, sum(info5) as info5,
        max(cast(info2 AS SIGNED)) as max_info2,
        max(cast(info3 AS SIGNED)) as max_info3
   from
      ( SELECT  a.server_id as server_id,e.server_name as server_name,
                a.id,a.`queue_datetime`, b.agent, a.qname_id as queue_id ,
               c.queue as queue_name,d.event,a.qevent_id,a.info1,a.info2,
               a.info3,a.info4,a.info5
            FROM  view_queue_stats a,tbl_qagent b, tbl_qname c, tbl_qevent d,
                tbl_server e
            WHERE  a.qagent_id=b.id
              AND  a.qname_id=c.id
              AND  a.qevent_id=d.id
              AND  a.server_id=e.id
              AND  DATE(a.queue_datetime) between '" . $start_date .
                                           "' AND '" . $end_date . "'
              AND  a.server_id IN ($server_name) 
      )as total
    GROUP BY  qevent_id,queue_id,server_id
    ORDER BY  length(server_name), server_name,queue_id,qevent_id. 

我认为通过分区视图搜索可以更快地执行我的查询。为了实现这一点,我应用了与分区相关的参数来创建视图但没有成功。

以下是SHOW CREATE VIEW的输出view_queue_stats;

CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER 
       VIEW `view_queue_stats`
       AS    select  `tbl_queue_stats_0116`.`id` AS `id`,
       `tbl_queue_stats_0116`.`server_id` AS `server_id`,
       `tbl_queue_stats_0116`.`uniqueid` AS `uniqueid`,
       `tbl_queue_stats_0116`.`queue_datetime` AS `queue_datetime`,
       `tbl_queue_stats_0116`.`queue_timestamp` AS `queue_timestamp`,
       `tbl_queue_stats_0116`.`qname_id` AS `qname_id`,
       `tbl_queue_stats_0116`.`qagent_id` AS `qagent_id`,
       `tbl_queue_stats_0116`.`qevent_id` AS `qevent_id`,
       `tbl_queue_stats_0116`.`info1` AS `info1`,
       `tbl_queue_stats_0116`.`info2` AS `info2`,
       `tbl_queue_stats_0116`.`info3` AS `info3`,
       `tbl_queue_stats_0116`.`info4` AS `info4`,
       `tbl_queue_stats_0116`.`info5` AS `info5`
    from  `tbl_queue_stats_0116`
    union  all 
select  `tbl_queue_stats_0216`.`id` AS `id`,
       `tbl_queue_stats_0216`.`server_id` AS `server_id`,
       `tbl_queue_stats_0216`.`uniqueid` AS `uniqueid`,
       `tbl_queue_stats_0216`.`queue_datetime` AS `queue_datetime`,
       `tbl_queue_stats_0216`.`queue_timestamp` AS `queue_timestamp`,
       `tbl_queue_stats_0216`.`qname_id` AS `qname_id`,
       `tbl_queue_stats_0216`.`qagent_id` AS `qagent_id`,
       `tbl_queue_stats_0216`.`qevent_id` AS `qevent_id`,
       `tbl_queue_stats_0216`.`info1` AS `info1`,
       `tbl_queue_stats_0216`.`info2` AS `info2`,
       `tbl_queue_stats_0216`.`info3` AS `info3`,
       `tbl_queue_stats_0216`.`info4` AS `info4`,
       `tbl_queue_stats_0216`.`info5` AS `info5`
    from  `tbl_queue_stats_0216`
    union  all
    ...

| utf8                 | utf8_general_ci      |

那么,有没有办法对视图进行分区?

2 个答案:

答案 0 :(得分:1)

你有十亿个server_ids吗?也许您可以使用较小的int,例如MEDIUMINT UNSIGNED,它是3个字节(而不是4个),限制为16M。同样适用于其他ID。 (较小 - >更多可缓存 - >更少I / O - >更快)

queue_timestamp是时间戳吗?如果是,为什么VARCHAR

cast(info2 AS SIGNED) - 您最好在插入数据之前清理数据,然后使用适当的数据类型(INT?)。

重要:不要隐藏函数中的列(DATE(a.queue_datetime)),它禁止使用索引;见下文。

大多数领域真的是可选的吗?如果没有,请说出NOT NULL,而不是NULL

重要:回到问题... 10个表中的UNION ALL将执行类似于PARTITIONed表,其中不会发生“分区修剪”。但是,UNION可能会更糟,因为它似乎生成包含所有数据的临时表,然后开始过滤。请为EXPLAIN SELECT ...提供查询。 (这应该证实或否定这种假设。它可能会产生很大的不同。)

重要: INDEX(server_id, queue_datetime)可能有助于提高效果。

所以,现在的问题是“修剪”是否会发生。可能的情况是query_datetime将结果限制为几个分区。表格是否基于query_datetimeSELECTs通常仅限于一个或两个表吗?

鉴于上述问题的正确答案,并且考虑到建议的更改,然后从VIEW更改为此将有助于:

PARTITION BY RANGE(TO_DAYS(query_datetime)) ...

但是,事实证明,分区并不是必需的。上面建议的INDEX(以及对WHERE的更改)在单个表上也同样出色。

但......还有一些问题。你提到了一个SELECT;还有其他人吗?修复一个查询的查询/架构可能会也可能不会帮助其他查询。你删除“旧”表/分区吗?如果是这样,分区可以很好地帮助。

回答这些问题,然后我们可以进行中途修正。

答案 1 :(得分:0)

检查下面给出的链接。这可能会对您有所帮助

http://dev.mysql.com/doc/refman/5.5/en/partitioning.html