Der Umgang mit der Objektart: DOMAIN

Forum für neue Firebird-Anwender.

Moderator: thorben.braun

bfuerchau
Beiträge: 485
Registriert: Mo 7. Mai 2018, 18:09
Kontaktdaten:

Wie ich eingangs schon beschrieb löse ich komplexe SQL's in parallele Einzelschritte auf.
Wenn du mit dem Konzept "CTE" und "Derived Table" bekannt bist, erklärt sich das nahezu von selbst.
In der BI-Welt (Business-Intelligence) bedarf es komplexer Abfrage von u.U. zig Tabellen zu einem großen Gesamtergebnis.
Der Nachteil bei Joins, ins besonders Gruppierungen, ist, dass kaum Indizes verwendet werden können.

Beispiel (simplifiziert):
with T1 as (
select k1, k2, sum(f1) f1
from Tab1
where ...
group by K1, K2
)
,T2 as (
select ka1, ka2, avg(f2) f2
from Tab2
group by ka1, ka2
)

select * from T1
inner join T2 on k1 = ka1 and k2 = ka2

Dies wird von mir nun zerlegt in
create table tempt1 ...
create index tempt1i1 on tempt1 (k1, k2)
create table tempt2
create index tempt2i1 on tempt2 (ka1, ka2)

insert into tempt1
select .... // Select 1 von oben

insert into tempt2
select ... // Sleect 2 von oben

//Final
select * from tempt1
inner join tempt2 on k1=ka1 and k2=ka2

Dies bedarf 2er paralleler Verbindungen. Je nach Komplexität gibt es eben bis zu 8 parallele Ausführungen.
Das Erstellen der Tabellen und Indizes dauert weniger als 1 Sekunde (durch Domains).
Die jeweiligen Selects können Indizes verwenden, da die Basistabellen passende Indizes haben (auch diese werden i.Ü. von mir nach Bedarf erstellt).
Der Final-Select bring die Daten dann in die Auswertung.

Zum Schluss gibts dann 2 "Drop Table", die übrigens die Indizes gleich mit löschen.

Das Hauptproblem bei der Betrachtung (betrifft übrigens jede DB) ist, dass CTE's tatsächlich keine echten Tabellen erstellen.
Verknüpft man wie oben 2 Gruppierte Ergebnisse, wird "von links nach rechts" abgearbeitet:
T1 wird nach Index (falls vorhanden) oder natural verarbeitet und gruppiert.
Dann wird je Gruppe aus T1 die passende Gruppe aus T2 ermittelt, wobei das bei Indexverwendung aus T1 u.U. auch direkt passiert.
Und dies kann da schon mal etwas länger dauern, ins besonders, wenn es für T2 keinen passenden Index gibt.

Durch die schrittweise Zerlegung und Bildung passender Indizes wird das Ergebnis z.T. drastisch beschleunigt.
Vor allem dann, wenn auf Grund der Aufgabenstellung auch schon mal gerne 20 - 30 Tabellen im Kontext verarbeitet werden.
Einen "order by" verwende ich grundsätzlich nicht mehr, da eine Sortierung i.d.R. durch den Frontend (z.B. Grid, Pivot) sowieso durch den User gesteuert wird.

In der BI-Branche wird da gerne mit vordefinierte Würfeln (Cubes) gearbeitet, die die Arbeitslast vorneweg nehmen. Leider kann das schnell unflexibel werden, da jede Veränderung (Feld dazu) eine komplette Neuberechnung erfordert.
Hinzu kommt, dass die Berechnung von Cubes auch schon mal gerne länger als 24 Stunden dauert und man somit nie auf aktuellen Zahlen eine Auswertung bekommt.
Gerd
Beiträge: 234
Registriert: Di 1. Okt 2019, 17:13

Hallo bfuerchau.
bfuerchau hat geschrieben: Mo 6. Apr 2020, 10:32 ... Wenn du mit dem Konzept "CTE" und ... bekannt bist, erklärt sich das nahezu von selbst. ...
Nein. CTE kenne ich vom Hörensagen (--> SQL SERVER 2012) - und somit nicht! Bisher reichten mir Views. In der 'BI-Branche' agiere nicht.

Danke für Deine ausführlichen Erklärungen.



Viele Grüße
Gerd
Linux Mint 21.3 Virginia Cinnamon 6.0.4
Firebird 5.0.0., Embedded, ISQL: LI-V5.0.0.1306
Lazarus 3.0.0 - FPC 3.2.2
Gerd
Beiträge: 234
Registriert: Di 1. Okt 2019, 17:13

Hallo.


Übrigens ...
Die Objektart DOMAIN benötigt man in Firebird spätestens dann, wenn man für seine DB-Tabelle(n) 'Aufzählungslisten' (Datentyp: ENUM -> ENUMERATE) benötigt.
Die ENUM (dt. Aufzählung) gibt es nicht als direkt zur Verfügung stehenden Datentyp. (Auch nicht in der Firebird Version 4.0 Beta 1.)
Aber laut Firebird Dokumentation lässt sich fast jeder Typ mit DOMAINEN 'emulieren' und so auch der Typ ENUM.

Beispiel:
Wenn Sie eine ENUM benötigen, welche bspw. die Werte Firebird, MySQL und MSSQL erlaubt, können Sie eine DOMAINE wie diese definieren:

Code: Alles auswählen

CREATE DOMAIN db_enum
AS varchar(20) CHECK (value IS NULL or VALUE IN ('Firebird','MySQL','MSSQL'));
Die Tabelle, die diese (DOMAIN) ENUM-Liste 'Firebird', 'MySQL', 'MSSQL' verwendet, könnte dann so aussehen:

Code: Alles auswählen

CREATE TABLE software (
id INTEGER,
Softwarebezeichnung db_enum
);
Mit der hier definierten DOMAIN db_enum werden im Feld Softwarebezeichnung die Werte
:: Firebird
:: MySQL
:: MSSQL
:: <null>
zugelassen.

D E M O

Code: Alles auswählen

gerd@gerd-MS-7641:~$ isql -z
ISQL Version: LI-T4.0.0.1902 Firebird 4.0 Beta 1
Use CONNECT or CREATE DATABASE to specify a database
SQL> connect '/home/gerd/Firebird/Datenbanken/testenum.fdb' user 'gerd' password 'geheimes_passwort';
Server version:
LI-T4.0.0.1902 Firebird 4.0 Beta 1
Database: '/home/gerd/Firebird/Datenbanken/testenum.fdb', User: GERD
SQL> SHOW TABLES;
There are no tables in this database
SQL> CREATE TABLE software (
CON> id INTEGER,
CON> Softwarebezeichnung db_enum
CON> );
SQL> INSERT INTO software (id, softwarebezeichnung) values (1, 'Firebird');
SQL> INSERT INTO software (id, softwarebezeichnung) values (2, 'MySQL');
SQL> INSERT INTO software (id, softwarebezeichnung) values (3, 'MSSQL');
SQL> INSERT INTO software (id, softwarebezeichnung) values (4, null);
SQL> SELECT * FROM software;

          ID SOFTWAREBEZEICHNUNG  
============ ==================== 
           1 Firebird             
           2 MySQL                
           3 MSSQL                
           4 <null>               

SQL> INSERT INTO software (id, softwarebezeichnung) values (5, 'Firebirdyyyyyyy');
Statement failed, SQLSTATE = 23000
validation error for column "SOFTWARE"."SOFTWAREBEZEICHNUNG", value "Firebirdyyyyyyy"
SQL> 
Viele Grüße
Gerd
Linux Mint 21.3 Virginia Cinnamon 6.0.4
Firebird 5.0.0., Embedded, ISQL: LI-V5.0.0.1306
Lazarus 3.0.0 - FPC 3.2.2
bfuerchau
Beiträge: 485
Registriert: Mo 7. Mai 2018, 18:09
Kontaktdaten:

Das ist das falsche Verständnis von dem Begriff ENUM aus Programmierersicht.
Was du da machst ist ein simpler Check-Constraint.

Ein ENUM wird als eine Liste von Ersatzwerten verstanden:

enum {
Default = 0,
Firebird = 1,
MySql = 2
:
}

Die DOMAIN ist vom Typ numerisch, der Update erlaubt aber
a) den numerischen Wert aus der Liste
b) den Zeichenwert aus der Liste
Beim Lesen wird immer der Zeichenwert ausgegeben.

Beim Einsatz von Frameworks in der Programmierung erfolgt dies durch die Runtime (z.B. EntityFramework).
Gerd
Beiträge: 234
Registriert: Di 1. Okt 2019, 17:13

bfuerchau hat geschrieben: Sa 25. Apr 2020, 10:50 Das ist das falsche Verständnis von dem Begriff ENUM aus Programmierersicht. ...
Hallo bfuerchau.

Aufmerksam mitgelesen. Ich stimme Dir voll zu. Habe das wirklich nicht ausreichend deutlich gemacht. :oops:

Der fließende Übergang zwischen der fehlenden Möglichkeit einer Aufzählungsliste und dann im weiteren Verlauf auf Check-Constraints einzugehen - was kein Typ ENUM darstellt - ist falsch. Aber auch Check-Constraints können hilfreich sein.

Ich lasse das oben aber mal so stehen, denn Du hast das ja hier klargestellt.
Danke.


Viele Grüße
Gerd
Linux Mint 21.3 Virginia Cinnamon 6.0.4
Firebird 5.0.0., Embedded, ISQL: LI-V5.0.0.1306
Lazarus 3.0.0 - FPC 3.2.2
Antworten