【发布时间】:2021-04-12 20:34:16
【问题描述】:
我正在尝试为我的自定义网络构建一个监控仪表板,在 Zabbix 中实现的那个不符合我的要求。
我为提取此信息而执行的查询。
SELECT ll.UF
,ll.unidade AS metric
,if(AVG(ll.ONLINE) = 0 AND AVG(ll.degra) = 0,3,if(AVG(ll.ONLINE) = 0 AND AVG(ll.degra) = 1,3,if(AVG(ll.ONLINE) = 0 AND AVG(ll.degra) > 0 AND AVG(ll.degra) < 1,3,if(AVG(ll.ONLINE) = 1 AND AVG(ll.degra) = 0,0,if(AVG(ll.ONLINE) = 1 AND AVG(ll.degra) = 1,1,if(AVG(ll.ONLINE) = 1 AND AVG(ll.degra) > 0 AND AVG(ll.degra) < 1,1,if(AVG(ll.degra) = 0 AND AVG(ll.ONLINE) > 0 AND AVG(ll.ONLINE) < 1,2,if(AVG(ll.degra) = 1 AND AVG(ll.ONLINE) > 0 AND AVG(ll.ONLINE) < 1,2,if(AVG(ll.degra) > 0 AND AVG(ll.degra) < 1 AND AVG(ll.ONLINE) > 0 AND AVG(ll.ONLINE) < 1,2,3))))))))) AS value
FROM
(
SELECT hh.*
,if(hh.falha=1,0,1) AS ONLINE
,if(hh.falha=2,1,0) AS degra
FROM
(
SELECT dfd1.*
,SUM(if(dfd2.name = 'Perda de Pacote' OR dfd2.name = 'Tempo de resposta de ping ICMP alto',2,if(dfd2.name = 'ICMP Ping Indisponível',1,0))) AS falha
FROM
(
SELECT AT1.*
,AT2.itemid
FROM
(
SELECT hb.*
FROM
(
SELECT HOST
,LEFT(HOST,2) AS UF
,SUBSTRING_INDEX(SUBSTRING_INDEX(HOST,'_',2),'_',-1) AS Operadora
,SUBSTRING_INDEX(SUBSTRING_INDEX(HOST,'_',-2),'_',1) AS unidade
,SUBSTRING_INDEX(HOST,'_',-1) AS tipo
,if( LEFT( SUBSTRING_INDEX(SUBSTRING_INDEX(HOST,'_',-2),'_',1),3) = 'HS.' ,
'hospital',if( LEFT( SUBSTRING_INDEX(SUBSTRING_INDEX(HOST,'_',-2),'_',1),3) = 'VI.' ,
'vidaeimagem',if( LEFT( SUBSTRING_INDEX(SUBSTRING_INDEX(HOST,'_',-2),'_',1),7) = 'HAPCLI.' ,
'hapclinica',if( LEFT( SUBSTRING_INDEX(SUBSTRING_INDEX(HOST,'_',-2),'_',1),3) = 'PA.' ,
'prontoatendimento',if( LEFT( SUBSTRING_INDEX(SUBSTRING_INDEX(HOST,'_',-2),'_',1),3) = 'CD.' ,
'centrodedistribuicao',if( LEFT( SUBSTRING_INDEX(SUBSTRING_INDEX(HOST,'_',-2),'_',1),8) = 'MEDPREV.' ,
'medprev',if( LEFT( SUBSTRING_INDEX(SUBSTRING_INDEX(HOST,'_',-2),'_',1),4) = 'LAB.' ,
'laboratorio',if( LEFT( SUBSTRING_INDEX(SUBSTRING_INDEX(HOST,'_',-2),'_',1),4) = 'ADM.' ,
'administrativo',if( LEFT( SUBSTRING_INDEX(SUBSTRING_INDEX(HOST,'_',-2),'_',1),4) = 'AMB.' ,
'ambulatorio','outros' ) ) ) ) ) ) ) ) ) AS modalidade
,hostid
FROM hosts
WHERE STATUS = 0
) AS hb
LEFT JOIN hosts_groups AS idgr
ON hb.hostid = idgr.hostid
WHERE idgr.groupid = 15
) AS AT1
LEFT JOIN items AS AT2
ON AT1.hostid = AT2.hostid
) AS dfd1
LEFT JOIN
(
SELECT gn2.itemid
,gn1.name
FROM
(
SELECT a1.*
FROM events AS a1
LEFT JOIN event_recovery AS a2
ON a1.eventid = a2.eventid
WHERE a2.r_eventid IS NULL
AND a1.value = 1
) AS gn1
LEFT JOIN functions AS gn2
ON gn1.objectid = gn2.triggerid
WHERE gn2.itemid IS NOT NULL
) AS dfd2
ON dfd1.itemid = dfd2.itemid
GROUP BY dfd1.host
) AS hh
) AS ll
GROUP BY ll.unidade
ORDER BY ll.UF ASC
,VALUE desc
我能够打开 Zabbix 数据库并进行我需要的查询,但是查询大约需要 15 秒并且消耗了大量处理(我在银行表之间使用了很多 INNER JOIN)。
CREATE TABLE `hosts` (
`hostid` BIGINT(20) UNSIGNED NOT NULL,
`proxy_hostid` BIGINT(20) UNSIGNED NULL DEFAULT NULL,
`host` VARCHAR(128) NOT NULL DEFAULT '' COLLATE 'utf8_bin',
`status` INT(11) NOT NULL DEFAULT '0',
`name` VARCHAR(128) NOT NULL DEFAULT '' COLLATE 'utf8_bin',
`flags` INT(11) NOT NULL DEFAULT '0',
`templateid` BIGINT(20) UNSIGNED NULL DEFAULT NULL,
`description` TEXT NOT NULL COLLATE 'utf8_bin',
`proxy_address` VARCHAR(255) NOT NULL DEFAULT '' COLLATE 'utf8_bin',
`auto_compress` INT(11) NOT NULL DEFAULT '1',
`discover` INT(11) NOT NULL DEFAULT '0',
PRIMARY KEY (`hostid`) USING BTREE,
INDEX `hosts_1` (`host`) USING BTREE,
INDEX `hosts_2` (`status`) USING BTREE,
INDEX `hosts_3` (`proxy_hostid`) USING BTREE,
INDEX `hosts_4` (`name`) USING BTREE,
INDEX `c_hosts_3` (`templateid`) USING BTREE,
CONSTRAINT `c_hosts_1` FOREIGN KEY (`proxy_hostid`) REFERENCES `zabbix`.`hosts` (`hostid`) ON UPDATE RESTRICT ON DELETE RESTRICT,
CONSTRAINT `c_hosts_3` FOREIGN KEY (`templateid`) REFERENCES `zabbix`.`hosts` (`hostid`) ON UPDATE RESTRICT ON DELETE CASCADE
)
COLLATE='utf8_bin'
ENGINE=InnoDB
;
表链接组与主机名
CREATE TABLE `hosts_groups` (
`hostgroupid` BIGINT(20) UNSIGNED NOT NULL,
`hostid` BIGINT(20) UNSIGNED NOT NULL,
`groupid` BIGINT(20) UNSIGNED NOT NULL,
PRIMARY KEY (`hostgroupid`) USING BTREE,
UNIQUE INDEX `hosts_groups_1` (`hostid`, `groupid`) USING BTREE,
INDEX `hosts_groups_2` (`groupid`) USING BTREE,
CONSTRAINT `c_hosts_groups_1` FOREIGN KEY (`hostid`) REFERENCES `zabbix`.`hosts` (`hostid`) ON UPDATE RESTRICT ON DELETE CASCADE,
CONSTRAINT `c_hosts_groups_2` FOREIGN KEY (`groupid`) REFERENCES `zabbix`.`hstgrp` (`groupid`) ON UPDATE RESTRICT ON DELETE CASCADE
)
COLLATE='utf8_bin'
ENGINE=InnoDB
;
链接要触发的项目的表
CREATE TABLE `items` (
`itemid` BIGINT(20) UNSIGNED NOT NULL,
`hostid` BIGINT(20) UNSIGNED NOT NULL,
`name` VARCHAR(255) NOT NULL DEFAULT '' COLLATE 'utf8_bin',
PRIMARY KEY (`itemid`) USING BTREE,
INDEX `items_1` (`hostid`, `key_`(255)) USING BTREE,
INDEX `items_3` (`status`) USING BTREE,
CONSTRAINT `c_items_1` FOREIGN KEY (`hostid`) REFERENCES `zabbix`.`hosts` (`hostid`) ON UPDATE RESTRICT ON DELETE CASCADE
)
COLLATE='utf8_bin'
ENGINE=InnoDB
;
将 event_recovery 链接到事件的表
CREATE TABLE `event_recovery` (
`eventid` BIGINT(20) UNSIGNED NOT NULL,
`r_eventid` BIGINT(20) UNSIGNED NOT NULL,
`c_eventid` BIGINT(20) UNSIGNED NULL DEFAULT NULL,
`correlationid` BIGINT(20) UNSIGNED NULL DEFAULT NULL,
`userid` BIGINT(20) UNSIGNED NULL DEFAULT NULL,
PRIMARY KEY (`eventid`) USING BTREE,
INDEX `event_recovery_1` (`r_eventid`) USING BTREE,
INDEX `event_recovery_2` (`c_eventid`) USING BTREE,
CONSTRAINT `c_event_recovery_1` FOREIGN KEY (`eventid`) REFERENCES `zabbix`.`events` (`eventid`) ON UPDATE RESTRICT ON DELETE CASCADE,
CONSTRAINT `c_event_recovery_2` FOREIGN KEY (`r_eventid`) REFERENCES `zabbix`.`events` (`eventid`) ON UPDATE RESTRICT ON DELETE CASCADE,
CONSTRAINT `c_event_recovery_3` FOREIGN KEY (`c_eventid`) REFERENCES `zabbix`.`events` (`eventid`) ON UPDATE RESTRICT ON DELETE CASCADE
)
COLLATE='utf8_bin'
ENGINE=InnoDB
;
事件
CREATE TABLE `events` (
`eventid` BIGINT(20) UNSIGNED NOT NULL,
`source` INT(11) NOT NULL DEFAULT '0',
`object` INT(11) NOT NULL DEFAULT '0',
`objectid` BIGINT(20) UNSIGNED NOT NULL DEFAULT '0',
`clock` INT(11) NOT NULL DEFAULT '0',
`value` INT(11) NOT NULL DEFAULT '0',
`acknowledged` INT(11) NOT NULL DEFAULT '0',
`ns` INT(11) NOT NULL DEFAULT '0',
`name` VARCHAR(2048) NOT NULL DEFAULT '' COLLATE 'utf8_bin',
`severity` INT(11) NOT NULL DEFAULT '0',
PRIMARY KEY (`eventid`) USING BTREE,
INDEX `events_1` (`source`, `object`, `objectid`, `clock`) USING BTREE,
INDEX `events_2` (`source`, `object`, `clock`) USING BTREE
)
COLLATE='utf8_bin'
ENGINE=InnoDB
;
表函数
CREATE TABLE `functions` (
`functionid` BIGINT(20) UNSIGNED NOT NULL,
`itemid` BIGINT(20) UNSIGNED NOT NULL,
`triggerid` BIGINT(20) UNSIGNED NOT NULL,
`name` VARCHAR(12) NOT NULL DEFAULT '' COLLATE 'utf8_bin',
`parameter` VARCHAR(255) NOT NULL DEFAULT '0' COLLATE 'utf8_bin',
PRIMARY KEY (`functionid`) USING BTREE,
INDEX `functions_1` (`triggerid`) USING BTREE,
INDEX `functions_2` (`itemid`, `name`, `parameter`) USING BTREE,
CONSTRAINT `c_functions_1` FOREIGN KEY (`itemid`) REFERENCES `zabbix`.`items` (`itemid`) ON UPDATE RESTRICT ON DELETE CASCADE,
CONSTRAINT `c_functions_2` FOREIGN KEY (`triggerid`) REFERENCES `zabbix`.`triggers` (`triggerid`) ON UPDATE RESTRICT ON DELETE CASCADE
)
COLLATE='utf8_bin'
ENGINE=I
所以我发现,如果我分别进行查询并通过 PHP(我用来构建仪表板的语言)将表格放在一起,效率会高得多。但是,我正在使用 PHP 将两个查询关联为一个。
使用 PHP 我提出以下要求:
<?PHP
//error_reporting(E_ERROR | E_PARSE);
$path2 = $_SERVER['DOCUMENT_ROOT'];
$path2 .= "/SCL/db/protect.php";
include($path2);
//this code is better identified at the beginning of this StackOverflow forum
$geral = "select ll.UF, ll.unidade as metric,
if(AVG(ll.ONLINE) = 0 AND avg(ll.degra) = 0,3,if(AVG(ll.ONLINE) = 0 AND avg(ll.degra) = 1,3,if(AVG(ll.ONLINE) = 0 AND avg(ll.degra) > 0 AND avg(ll.degra) < 1,3,if(AVG(ll.ONLINE) = 1 AND avg(ll.degra) = 0,0,if(AVG(ll.ONLINE) = 1 AND avg(ll.degra) = 1,1,if(AVG(ll.ONLINE) = 1 AND avg(ll.degra) > 0 AND avg(ll.degra) < 1,1,if(AVG(ll.degra) = 0 AND avg(ll.ONLINE) > 0 AND avg(ll.ONLINE) < 1,2,if(AVG(ll.degra) = 1 AND avg(ll.ONLINE) > 0 AND avg(ll.ONLINE) < 1,2,if(avg(ll.degra) > 0 AND avg(ll.degra) < 1 AND avg(ll.ONLINE) > 0 AND avg(ll.ONLINE) < 1,2,3))))))))) AS value
FROM (SELECT hh.*, if(hh.falha=1,0,1) AS ONLINE,
if(hh.falha=2,1,0) AS degra
FROM (SELECT dfd1.*, sum(if(dfd2.name = 'Perda de Pacote' OR dfd2.name = 'Tempo de resposta de ping ICMP alto',2,if(dfd2.name = 'ICMP Ping Indisponível',1,0))) AS falha
FROM (SELECT AT1.*, AT2.itemid FROM (SELECT hb.*
FROM (
SELECT HOST,
LEFT(HOST,2) AS UF,
SUBSTRING_INDEX(SUBSTRING_INDEX(HOST,'_',2),'_',-1) AS Operadora,
SUBSTRING_INDEX(SUBSTRING_INDEX(HOST,'_',-2),'_',1) AS unidade,
SUBSTRING_INDEX(HOST,'_',-1) as tipo,
if( LEFT( SUBSTRING_INDEX(SUBSTRING_INDEX(HOST,'_',-2),'_',1),3) = 'HS.' , 'hospital', if( LEFT( SUBSTRING_INDEX(SUBSTRING_INDEX(HOST,'_',-2),'_',1),3) = 'VI.' , 'vidaeimagem', if( LEFT( SUBSTRING_INDEX(SUBSTRING_INDEX(HOST,'_',-2),'_',1),7) = 'HAPCLI.' , 'hapclinica', if( LEFT( SUBSTRING_INDEX(SUBSTRING_INDEX(HOST,'_',-2),'_',1),3) = 'PA.' , 'prontoatendimento', if( LEFT( SUBSTRING_INDEX(SUBSTRING_INDEX(HOST,'_',-2),'_',1),3) = 'CD.' , 'centrodedistribuicao', if( LEFT( SUBSTRING_INDEX(SUBSTRING_INDEX(HOST,'_',-2),'_',1),8) = 'MEDPREV.' , 'medprev', if( LEFT( SUBSTRING_INDEX(SUBSTRING_INDEX(HOST,'_',-2),'_',1),4) = 'LAB.' , 'laboratorio', if( LEFT( SUBSTRING_INDEX(SUBSTRING_INDEX(HOST,'_',-2),'_',1),4) = 'ADM.' , 'administrativo', if( LEFT( SUBSTRING_INDEX(SUBSTRING_INDEX(HOST,'_',-2),'_',1),4) = 'AMB.' , 'ambulatorio', 'outros' ) ) ) ) ) ) ) ) ) as modalidade,
hostid
FROM hosts WHERE STATUS = 0 ) AS hb
LEFT JOIN hosts_groups AS idgr
ON hb.hostid = idgr.hostid
WHERE idgr.groupid = 15) AS AT1
LEFT JOIN items AS AT2 ON AT1.hostid = AT2.hostid) AS dfd1
LEFT JOIN (SELECT gn2.itemid, gn1.name from (SELECT a1.* FROM events AS a1 LEFT JOIN event_recovery AS a2 ON a1.eventid = a2.eventid WHERE a2.r_eventid IS NULL AND a1.value = 1) AS gn1 LEFT JOIN functions AS gn2 ON gn1.objectid = gn2.triggerid WHERE gn2.itemid IS NOT NULL) AS dfd2
ON dfd1.itemid = dfd2.itemid
GROUP BY dfd1.host) AS hh) AS ll";
if(!empty($_POST["UF"]) && empty($_POST["modalidade"])){
$uf = " '" . str_replace(" ","','",$_POST["UF"]) . "' ";
$sql2 = $geral . "
where ll.uf in (" . $uf . ")
GROUP BY ll.unidade";
}elseif (empty($_POST["UF"]) && !empty($_POST["modalidade"])){
$modalidade = " '" . str_replace(" ","','",$_POST["modalidade"]) . "' ";
$sql2 = $geral . "
where ll.modalidade in (" . $modalidade . ")
GROUP BY ll.unidade";
}elseif (!empty($_POST["UF"]) && !empty($_POST["modalidade"])){
$uf = " '" . str_replace(" ","','",$_POST["UF"]) . "' ";
$modalidade = " '" . str_replace(" ","','",$_POST["modalidade"]) . "' ";
$sql2 = $geral . "
where ll.uf in (" . $uf . ")
and ll.modalidade in (" . $modalidade . ")
GROUP BY ll.unidade";
}else{
$sql2 = $geral . "
GROUP BY ll.unidade";
}
if(!empty($_POST["separa"])){
$sql2 = $sql2 . "
ORDER BY ll.UF ASC, VALUE desc";
}else{
$sql2 = $sql2 . "
ORDER BY VALUE desc";
}
if(!empty($_POST["falha"])){
$sql2 = 'SELECT i.* FROM (' . $sql2 . ') AS i WHERE i.VALUE != 0';
}
$stmt2 = $connect2->prepare($sql2);
$result2 = $stmt2->execute();
$val = $stmt2->rowCount();
$ds = "";
echo '<div class="lista">';
if($val > 0){
while($row = $stmt2->fetch(PDO::FETCH_OBJ)){
if(!empty($_POST["separa"])){
if ($ds <> $row->UF) {
$ds = $row->UF;
echo '</div><h2><span class="line-center">' . $row->UF . '</span></h2><div class="lista">';
}
}
if($row->value == 0){
$cor = 'green';
}elseif($row->value == 1){
$cor = 'orange';
}elseif($row->value == 2){
$cor = 'yellow';
}else{
$cor = 'red';
}
echo '<div class="usu"><span class="textON">' . $row->UF . "-" . str_replace("MEDPREV.","FMED.",str_replace("HS.","HOSP.",str_replace("HAPCLI.","HAP.",$row->metric))) . '</span><div class="circulo ' . $cor . '"></div></div>';
}
echo '</div>';
}else{
echo "Sem Falha";
echo '</div>';
}
?>
如果有人知道任何可以帮助我在提取信息后操纵查询结果的工具,我是否会在这里寻求帮助以找到解决我这个困境的方法?
【问题讨论】:
-
显示 SQL。在查询中的表中显示
show create table {tablename}。为您的 SQL 显示EXPLAIN {query}。表格的图像没有足够的信息来评估。假设您的数据集是有限的,正确的indexing 应该可以解决性能问题。在 PHP 中编写加入是试图完成数据库的工作。正确索引它,您不需要这样做。 -
为什么不用zabbix php api?