Skip to content
This repository has been archived by the owner on Dec 13, 2022. It is now read-only.

Commit

Permalink
enh(resource-status): performance optimizations (#10323)
Browse files Browse the repository at this point in the history
* enh(resource-status): escape "_" character to use indexed search

* enh(resources): use EXISTS statement instead of INNER JOIN
  • Loading branch information
adr-mo committed Oct 22, 2021
1 parent edcdf92 commit 07394c9
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 64 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -69,9 +69,9 @@ public function prepareSubQueryWithAcl(
StatementCollector $collector,
array $accessGroupIds
): string {
$aclSubQuery = ' INNER JOIN `:dbstg`.`centreon_acl` AS host_acl ON host_acl.host_id = h.host_id
$aclSubQuery = ' EXISTS (SELECT 1 FROM `:dbstg`.`centreon_acl` AS host_acl WHERE host_acl.host_id = h.host_id
AND host_acl.service_id IS NULL
AND host_acl.group_id IN (' . implode(',', $accessGroupIds) . ') ';
AND host_acl.group_id IN (' . implode(',', $accessGroupIds) . ') LIMIT 1) ';

return $this->prepareSubQuery($filter, $collector, $aclSubQuery);
}
Expand All @@ -89,7 +89,7 @@ private function prepareSubQuery(
StatementCollector $collector,
?string $aclSubQuery
): string {
$sql = "SELECT DISTINCT
$sql = "SELECT
h.host_id AS `id`,
'host' AS `type`,
h.name AS `name`,
Expand Down Expand Up @@ -160,11 +160,6 @@ private function prepareSubQuery(
AND host_cvl.service_id = 0
AND host_cvl.name = "CRITICALITY_LEVEL"';

// set ACL limitations
if ($aclSubQuery !== null) {
$sql .= $aclSubQuery;
}

$hasWhereCondition = false;

$this->sqlRequestTranslator->setConcordanceArray($this->hostConcordances);
Expand All @@ -179,9 +174,15 @@ private function prepareSubQuery(
$sql .= $searchRequest;
}

// set ACL limitations
if ($aclSubQuery !== null) {
$sql .= ($hasWhereCondition ? ' AND ' : ' WHERE ') . $aclSubQuery;
$hasWhereCondition = true;
}

// show active hosts and aren't related to some module
$sql .= ($hasWhereCondition ? ' AND ' : ' WHERE ')
. 'h.enabled = 1 AND h.name NOT LIKE "_Module_%"';
. 'h.enabled = 1 AND h.name NOT LIKE "\_Module\_%"';

// apply the state filter to SQL query
if ($filter->getStates() && !$filter->hasState(ResourceServiceInterface::STATE_ALL)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,9 +69,12 @@ public function prepareSubQueryWithAcl(
StatementCollector $collector,
array $accessGroupIds
): string {
$aclSubQuery = ' INNER JOIN `:dbstg`.`centreon_acl` AS service_acl ON service_acl.host_id = s.host_id
AND service_acl.service_id = s.service_id
AND service_acl.group_id IN (' . implode(',', $accessGroupIds) . ') ';
$aclSubQuery = ' EXISTS (
SELECT 1 FROM `:dbstg`.`centreon_acl` AS service_acl
WHERE service_acl.host_id = s.host_id
AND service_acl.service_id = s.service_id
AND service_acl.group_id IN (' . implode(',', $accessGroupIds) . ')
LIMIT 1) ';

return $this->prepareSubQuery($filter, $collector, $aclSubQuery);
}
Expand All @@ -89,7 +92,7 @@ private function prepareSubQuery(
StatementCollector $collector,
?string $aclSubQuery
): string {
$sql = "SELECT DISTINCT
$sql = "SELECT
SUBSTRING(s.description, 6) AS `id`,
'metaservice' AS `type`,
s.display_name AS `name`,
Expand Down Expand Up @@ -155,17 +158,18 @@ private function prepareSubQuery(
FROM `:dbstg`.`services` AS s
INNER JOIN `:dbstg`.`hosts` sh
ON sh.host_id = s.host_id
AND sh.name LIKE '_Module_Meta%'
AND sh.name LIKE '\_Module\_Meta%'
AND sh.enabled = 1";

// show active services only
$sql .= ' WHERE s.enabled = 1 ';


// set ACL limitations
if ($aclSubQuery !== null) {
$sql .= $aclSubQuery;
$sql .= ' AND ' . $aclSubQuery;
}

// show active services only
$sql .= ' WHERE s.enabled = 1';

// apply the state filter to SQL query
if ($filter->getStates() && !$filter->hasState(ResourceServiceInterface::STATE_ALL)) {
$sqlState = [];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,9 +71,12 @@ public function prepareSubQueryWithAcl(
StatementCollector $collector,
array $accessGroupIds
): string {
$aclSubQuery = ' INNER JOIN `:dbstg`.`centreon_acl` AS service_acl ON service_acl.host_id = s.host_id
AND service_acl.service_id = s.service_id
AND service_acl.group_id IN (' . implode(',', $accessGroupIds) . ') ';
$aclSubQuery = ' EXISTS (
SELECT 1 FROM `:dbstg`.`centreon_acl` AS service_acl
WHERE service_acl.host_id = s.host_id
AND service_acl.service_id = s.service_id
AND service_acl.group_id IN (' . implode(',', $accessGroupIds) . ')
LIMIT 1) ';

return $this->prepareSubQuery($filter, $collector, $aclSubQuery);
}
Expand Down Expand Up @@ -178,28 +181,6 @@ private function prepareSubQuery(
AND service_cvl.service_id = s.service_id
AND service_cvl.name = "CRITICALITY_LEVEL"';

// set ACL limitations
if ($aclSubQuery !== null) {
$sql .= $aclSubQuery;
}

// apply the service group filter to SQL query
if ($filter->getServicegroupIds()) {
$groupList = [];

foreach ($filter->getServicegroupIds() as $index => $groupId) {
$key = ":serviceServicegroupId_{$index}";

$groupList[] = $key;
$collector->addValue($key, $groupId, \PDO::PARAM_INT);
}

$sql .= ' INNER JOIN `:dbstg`.`services_servicegroups` AS ssg
ON ssg.host_id = s.host_id
AND ssg.service_id = s.service_id
AND ssg.servicegroup_id IN (' . implode(', ', $groupList) . ') ';
}

$hasWhereCondition = false;

$this->sqlRequestTranslator->setConcordanceArray($this->serviceConcordances);
Expand All @@ -218,6 +199,29 @@ private function prepareSubQuery(
$sql .= ($hasWhereCondition ? ' AND ' : ' WHERE ')
. 's.enabled = 1';

// set ACL limitations
if ($aclSubQuery !== null) {
$sql .= ' AND ' . $aclSubQuery;
}

// apply the service group filter to SQL query
if ($filter->getServicegroupNames()) {
$groupList = [];

foreach ($filter->getServicegroupNames() as $index => $groupName) {
$key = ":serviceServicegroupName_{$index}";

$groupList[] = $key;
$collector->addValue($key, $groupName, \PDO::PARAM_STR);
}

$sql .= ' AND EXISTS (SELECT 1 FROM `:dbstg`.`services_servicegroups` AS ssg
WHERE ssg.host_id = s.host_id AND ssg.service_id = s.service_id
AND EXISTS (SELECT 1 FROM `:dbstg`.`servicegroups` AS sg
WHERE ssg.servicegroup_id = sg.servicegroup_id
AND sg.id = ssg.id AND sg.name IN (' . implode(', ', $groupList) . ') LIMIT 1) LIMIT 1)';
}

// apply the state filter to SQL query
if ($filter->getStates() && !$filter->hasState(ResourceServiceInterface::STATE_ALL)) {
$sqlState = [];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ final class ResourceRepositoryRDB extends AbstractRepositoryDRB implements Resou
private $accessGroups = [];

/**
* @var array Association of resource search parameters
* @var array<string, string> Association of resource search parameters
*/
private $resourceConcordances = [
'id' => 'resource.id',
Expand Down Expand Up @@ -162,7 +162,7 @@ public function findResources(ResourceFilter $filter): array
}

$collector = new StatementCollector();
$request = 'SELECT SQL_CALC_FOUND_ROWS DISTINCT '
$request = 'SELECT SQL_CALC_FOUND_ROWS '
. 'resource.id, resource.type, resource.name, resource.alias, resource.fqdn, '
. 'resource.host_id, resource.service_id, '
. 'resource.status_code, resource.status_name, resource.status_severity_code, ' // status
Expand Down Expand Up @@ -211,11 +211,26 @@ function ($accessGroup) {
return [];
}

$request .= implode('UNION ALL ', $subRequests);
$request .= implode(' UNION ALL ', $subRequests);
unset($subRequests);

$request .= ') AS `resource`';

$hasWhereCondition = false;

// Search
$this->sqlRequestTranslator->setConcordanceArray($this->resourceConcordances);
try {
$searchRequest = $this->sqlRequestTranslator->translateSearchParameterToSql();
} catch (RequestParametersTranslatorException $ex) {
throw new RepositoryException($ex->getMessage(), 0, $ex);
}

if ($searchRequest !== null) {
$hasWhereCondition = true;
$request .= $searchRequest;
}

// apply the host group filter to SQL query
if ($filter->getHostgroupIds()) {
$groupList = [];
Expand All @@ -226,35 +241,35 @@ function ($accessGroup) {
$collector->addValue($key, $groupId, \PDO::PARAM_INT);
}

$request .= ' INNER JOIN `:dbstg`.`hosts_hostgroups` AS hhg
ON hhg.host_id = resource.host_id
AND hhg.hostgroup_id IN (' . implode(', ', $groupList) . ') ';
$request .= ($hasWhereCondition === false) ? ' WHERE ' : ' AND ';
$hasWhereCondition = true;

$request .= ' EXISTS (
SELECT 1 FROM `:dbstg`.`hosts_hostgroups` AS hhg
WHERE hhg.host_id = resource.host_id
AND EXISTS (
SELECT 1 FROM `:dbstg`.`hostgroups` AS hg
WHERE hg.hostgroup_id = hhg.hostgroup_id AND hg.name IN (' . implode(', ', $groupList) . ')
LIMIT 1)
LIMIT 1) ';
}

/**
* If we specify that user only wants resources with available performance datas.
* Then only resources with existing metrics referencing index_data services will be returned.
*/
if ($filter->getOnlyWithPerformanceData() === true) {
$request .= ' INNER JOIN `:dbstg`.index_data AS idata
ON idata.host_id = resource.parent_id
$request .= $hasWhereCondition ? ' AND ' : ' WHERE ';
$request .= ' EXISTS (
SELECT 1 FROM `:dbstg`.index_data AS idata
WHERE idata.host_id = resource.parent_id
AND idata.service_id = resource.id
AND resource.type = "service"
INNER JOIN `:dbstg`.metrics AS m
ON m.index_id = idata.id
AND m.hidden = "0" ';
}

// Search
$this->sqlRequestTranslator->setConcordanceArray($this->resourceConcordances);
try {
$searchRequest = $this->sqlRequestTranslator->translateSearchParameterToSql();
} catch (RequestParametersTranslatorException $ex) {
throw new RepositoryException($ex->getMessage(), 0, $ex);
AND EXISTS (SELECT 1 FROM `:dbstg`.metrics AS m
WHERE m.index_id = idata.id
AND m.hidden = "0" LIMIT 1) LIMIT 1) ';
}

$request .= $searchRequest !== null ? $searchRequest : '';

foreach ($this->sqlRequestTranslator->getSearchValues() as $key => $data) {
$collector->addValue($key, current($data), key($data));
}
Expand Down

0 comments on commit 07394c9

Please sign in to comment.