我已经从大约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 |
那么,有没有办法对视图进行分区?
答案 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_datetime
? SELECTs
通常仅限于一个或两个表吗?
鉴于上述问题的正确答案,并且考虑到建议的更改,然后从VIEW
更改为此将有助于:
PARTITION BY RANGE(TO_DAYS(query_datetime)) ...
但是,事实证明,分区并不是必需的。上面建议的INDEX
(以及对WHERE
的更改)在单个表上也同样出色。
但......还有一些问题。你提到了一个SELECT
;还有其他人吗?修复一个查询的查询/架构可能会也可能不会帮助其他查询。你删除“旧”表/分区吗?如果是这样,分区可以很好地帮助。
回答这些问题,然后我们可以进行中途修正。
答案 1 :(得分:0)
检查下面给出的链接。这可能会对您有所帮助