Ich brauche einige Zahlen zu produzieren, habe ich eine Abfrage entwickelt, um das gewünschte Ergebnis von meinen "Kunden" zu bekommen. Diese Abfrage basiert auf einer Tabelle, die eine Million Datensätze enthält. Normalerweise verwende ich MariaDB dafür, und ich bekomme ein Ergebnis in ~ 7s. Diese Ausführungszeit ist durchaus geeignet, aber ich möchte noch einmal optimieren, um meine Fähigkeiten zu verbessern. Nach ein paar Recherchen stieß ich auf ein paar Posts, die sagten "MySQL ist in Ordnung, aber nicht auf Tabellen> 1M Datensätze, müssen Sie etwas anderes einschalten" PostgreSQL wurde mehrmals zitiert. So habe ich PostgreSQL installiert und meine Tabellen, Indizes und Daten kopiert. Ich führte die gleiche Abfrage, und ich hatte ein Ergebnis in ~ 12sMariaDB/PostreSQL - Abfrage Optimierung
Ich weiß weniger PostgreSQL, ich glaube, ich habe nicht die Besonderheiten der Sprache verwendet. So für jetzt bleibe ich bei MariaDB. Haben Sie eine Idee, die Ausführungszeit zu verbessern?
Hier meine Frage:
select categorie.cat
,dhu_type.type
,COUNT(DISTINCT(
CASE WHEN dhu.date between '2013-01-01' and '2013-12-31'
THEN dhu.id
END)
) AS "2013"
,COUNT(DISTINCT(
CASE WHEN dhu.date between '2014-01-01' and '2014-12-31'
THEN dhu.id
END)
) AS "2014"
,COUNT(DISTINCT(
CASE WHEN dhu.date between '2015-01-01' and '2015-12-31'
THEN dhu.id
END)
) AS "2015"
,COUNT(DISTINCT(
CASE WHEN dhu.date between '2016-01-01' and '2016-12-31'
THEN dhu.id
END)
) AS "2016"
from dhu
inner join dhu_type on dhu.type_id = dhu_type.id
inner join patient on dhu.patient_id=patient.id
inner join fa on patient.id = fa.patient_id
inner join categorie on categorie.id = fa.cat_id
group by cat,dhu_type.type
ich meine Frage mit einem Diagramm vervollständigen
Hier ist die CREATE TABLE:
/*!40101 SET @[email protected]@CHARACTER_SET_CLIENT */;
/*!40101 SET NAMES utf8 */;
/*!50503 SET NAMES utf8mb4 */;
/*!40014 SET @[email protected]@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @[email protected]@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
CREATE TABLE IF NOT EXISTS `categorie` (
`id` tinyint(3) unsigned NOT NULL AUTO_INCREMENT,
`cat` varchar(50) NOT NULL DEFAULT 'neonat',
PRIMARY KEY (`id`,`cat`)
) ENGINE=InnoDB AUTO_INCREMENT=16 DEFAULT CHARSET=utf8;
CREATE TABLE IF NOT EXISTS `cp` (
`id` smallint(5) unsigned NOT NULL AUTO_INCREMENT,
`cp` varchar(5) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `cp` (`cp`)
) ENGINE=InnoDB AUTO_INCREMENT=4096 DEFAULT CHARSET=utf8;
CREATE TABLE IF NOT EXISTS `dhu` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`patient_id` int(10) unsigned NOT NULL,
`date` date NOT NULL,
`type_id` tinyint(3) unsigned NOT NULL,
PRIMARY KEY (`id`),
KEY `FK_dhu_patient` (`patient_id`),
KEY `FK_dhu_dhu_type` (`type_id`),
CONSTRAINT `FK_dhu_dhu_type` FOREIGN KEY (`type_id`) REFERENCES `dhu_type` (`id`),
CONSTRAINT `FK_dhu_patient` FOREIGN KEY (`patient_id`) REFERENCES `patient` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=953590 DEFAULT CHARSET=utf8;
CREATE TABLE IF NOT EXISTS `dhu_import` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`noip` bigint(10) unsigned zerofill NOT NULL,
`date` date NOT NULL,
`cp` varchar(5) NOT NULL,
`type` varchar(4) NOT NULL,
PRIMARY KEY (`id`),
KEY `noip` (`noip`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE IF NOT EXISTS `dhu_type` (
`id` tinyint(3) unsigned NOT NULL AUTO_INCREMENT,
`type` varchar(4) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `type` (`type`)
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8;
CREATE TABLE IF NOT EXISTS `dpt` (
`dpt` tinyint(3) unsigned DEFAULT NULL,
`abrev` char(3) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE IF NOT EXISTS `fa` (
`patient_id` int(10) unsigned NOT NULL,
`cat_id` tinyint(3) unsigned NOT NULL,
PRIMARY KEY (`patient_id`,`cat_id`),
KEY `idx_cat_id_pat_id` (`cat_id`,`patient_id`),
CONSTRAINT `FK_fa_patient` FOREIGN KEY (`patient_id`) REFERENCES `patient` (`id`),
CONSTRAINT `FK_fa_categorie` FOREIGN KEY (`cat_id`) REFERENCES `categorie` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE IF NOT EXISTS `fa_import` (
`noip` bigint(10) unsigned zerofill NOT NULL,
`cat` varchar(50) NOT NULL,
PRIMARY KEY (`noip`,`cat`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT;
CREATE TABLE IF NOT EXISTS `patient` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`noip` bigint(10) unsigned zerofill NOT NULL,
`cp_id` smallint(5) unsigned NOT NULL,
PRIMARY KEY (`id`),
KEY `FK_patient_cp` (`cp_id`),
CONSTRAINT `FK_patient_cp` FOREIGN KEY (`cp_id`) REFERENCES `cp` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=262141 DEFAULT CHARSET=utf8;
/*!40101 SET SQL_MODE=IFNULL(@OLD_SQL_MODE, '') */;
/*!40014 SET FOREIGN_KEY_CHECKS=IF(@OLD_FOREIGN_KEY_CHECKS IS NULL, 1, @OLD_FOREIGN_KEY_CHECKS) */;
/*!40101 SET [email protected]_CHARACTER_SET_CLIENT */;
Hier ist die Abfrage erklären:
Hier eine Modifikation Verbesserung der Leistung (Wahlen statt categorie.cat categorie.id):
Hier ist die beste beste Abfrage fand ich dank @RickJames & @BillKarwin
select categorie.cat
,dhu_type.`type`
,t.`2013`
,t.`2014`
,t.`2015`
,t.`2016`
from (select fa.cat_id as catid
,dhu.type_id typid
,COUNT(DISTINCT(
CASE WHEN dhu.date between '2013-01-01' and '2013-12-31'
THEN dhu.id
END)
) AS "2013"
,COUNT(DISTINCT(
CASE WHEN dhu.date between '2014-01-01' and '2014-12-31'
THEN dhu.id
END)
) AS "2014"
,COUNT(DISTINCT(
CASE WHEN dhu.date between '2015-01-01' and '2015-12-31'
THEN dhu.id
END)
) AS "2015"
,COUNT(DISTINCT(
CASE WHEN dhu.date between '2016-01-01' and '2016-12-31'
THEN dhu.id
END)
) AS "2016"
from dhu
inner join patient on dhu.patient_id=patient.id
inner join fa on patient.id = fa.patient_id
group by fa.cat_id, dhu.type_id) t
inner join categorie on t.catid = categorie.id
inner join dhu_type on t.typid = dhu_type.id
order by categorie.cat,dhu_type.`type`
Machen Sie innere Verbindung Fa, Patienten, Kategorie statt. – jarlh
Sie haben Recht, die Abfrage ist lesbarer, aber die Ausführungszeit ist gleich. –
Bedingte Aggregation/FILTER #GIYF – wildplasser