SQL Tipps und Tricks Part III 08.02.2012



Ähnliche Dokumente
Einstieg in das SQL- und Datenbanktuning Loblied auf den Tabellen-Index!

SQL für Trolle. mag.e. Dienstag, Qt-Seminar

Projektbericht Gruppe 12. Datenbanksysteme WS 05/ 06. Gruppe 12. Martin Tintel Tatjana Triebl. Seite 1 von 11

Informatik 12 Datenbanken SQL-Einführung

MySQL: Einfaches Rechnen.

Urs Meier Art der Info Technical Info (Februar 2002) Aus unserer Projekterfahrung und Forschung

Mengenvergleiche: Alle Konten außer das, mit dem größten Saldo.

php Hier soll ein Überblick über das Erstellen von php Programmen gegeben werden. Inhaltsverzeichnis 1.Überblick Parameterübergabe...

Universität Augsburg, Institut für Informatik WS 2006/2007 Dr. W.-T. Balke 27. Nov M. Endres, A. Huhn, T. Preisinger Lösungsblatt 5

mysql - Clients MySQL - Abfragen eine serverbasierenden Datenbank

Datenbanken für Online Untersuchungen

Professionelle Seminare im Bereich MS-Office

7. Datenbank-Zugriff. Vorlesung und Übung Dr. Peter Pfahler Institut für Informatik Universität Paderborn. Zum Beispiel aus PHP-Skripten: Client 7-2

Beispiel 1: Filmdatenbank

Dipl. Inf. Dipl. Math. Y. Orkunoglu Datum:

PHP und MySQL. Integration von MySQL in PHP. Zellescher Weg 12 Willers-Bau A109 Tel Michael Kluge (michael.kluge@tu-dresden.

SQL-Injection. Seite 1 / 16

105.3 SQL-Datenverwaltung

MySQL Queries on "Nmap Results"

SQL Teil 2. SELECT Projektion Selektion Vereinigung, Schnitt, Differenz Verbund Komplexer SELECT-Ausdruck

SQL Tipps und Tricks Part II

Datenbanktechnologie mit praktischen Übungen in MySQL und PHP

PHP - Projekt Personalverwaltung. Erstellt von James Schüpbach

PostgreSQL unter Debian Linux

DBS ::: SERIE 5. Join Right Semi- Join Left Semi-Join Projektion Selektion Fremdschlüssel. Kreuzprodukt

SAMMEL DEINE IDENTITÄTEN::: NINA FRANK :: :: WINTERSEMESTER 08 09

MIN oder MAX Bildung per B*Tree Index Hint

Interaktive Webseiten mit PHP und MySQL

Access [basics] Gruppierungen in Abfragen. Beispieldatenbank. Abfragen gruppieren. Artikel pro Kategorie zählen

DATENBANKEN SQL UND SQLITE VON MELANIE SCHLIEBENER

1. Einführung Erstellung einer Teillieferung Erstellung einer Teilrechnung 6

Whitepaper. Produkt: combit Relationship Manager. Datensatzhistorie mit dem SQL Server 2000 und combit GmbH Untere Laube Konstanz

Fakultät für Informatik & Wirtschaftsinformatik DB & IS II - SS Metadaten

Handbuch zur Anlage von Turnieren auf der NÖEV-Homepage

Stellen Sie bitte den Cursor in die Spalte B2 und rufen die Funktion Sverweis auf. Es öffnet sich folgendes Dialogfenster

MySQL Installation. AnPr

SQL und MySQL. Kristian Köhntopp

SEMINAR Modifikation für die Nutzung des Community Builders

Aber zuerst: Was versteht man unter Stromverbrauch im Standby-Modus (Leerlaufverlust)?

Binäre Bäume. 1. Allgemeines. 2. Funktionsweise. 2.1 Eintragen

Die bisher bereits bekannten Aggregatsfunktionen MIN, MAX, SUM, AVG, COUNT, VARIANCE und STDDEV wurden um FIRST und LAST erweitert.

Datumsangaben, enthält mindestens Jahr, Monat, Tag

SQL structured query language

Anleitung über den Umgang mit Schildern

Erweiterung der Aufgabe. Die Notenberechnung soll nicht nur für einen Schüler, sondern für bis zu 35 Schüler gehen:

Labor 3 - Datenbank mit MySQL

OPERATIONEN AUF EINER DATENBANK

GEVITAS Farben-Reaktionstest

Oracle: Abstrakte Datentypen:

ltlasten in der Registrierdatenbank löschen

Apache HBase. A BigTable Column Store on top of Hadoop

Einfügen von Bildern innerhalb eines Beitrages

Datenbanken SQL Einführung Datenbank in MySQL einrichten mit PhpMyAdmin

Aufbau des SELECT-Befehls. Im Folgenden werden zunächst Abfragen aus einer Tabelle vorgenommen.

In diesem Thema lernen wir die Grundlagen der Datenbanken kennen und werden diese lernen einzusetzen. Access. Die Grundlagen der Datenbanken.

Lineargleichungssysteme: Additions-/ Subtraktionsverfahren

Reporting Services und SharePoint 2010 Teil 1

SQL Tutorial. SQL - Tutorial SS 06. Hubert Baumgartner. INSO - Industrial Software

Was meinen die Leute eigentlich mit: Grexit?

2.5.2 Primärschlüssel

Views in SQL. 2 Anlegen und Verwenden von Views 2

SQL. strukturierte Datenbankabfragesprache eine Datenbanksprache zur. Structured Query Language:

Erste Schritte mit TeamSpeak 3

Suchmaschinen. Universität Augsburg, Institut für Informatik SS 2014 Prof. Dr. W. Kießling 23. Mai 2014 Dr. M. Endres, F. Wenzel Lösungsblatt 6

SQL Performance - Tips Do's & Don'ts

Access [basics] Rechnen in Berichten. Beispieldatenbank. Datensatzweise berechnen. Berechnung im Textfeld. Reporting in Berichten Rechnen in Berichten

Tipp III: Leiten Sie eine immer direkt anwendbare Formel her zur Berechnung der sogenannten "bedingten Wahrscheinlichkeit".

! " # $ " % & Nicki Wruck worldwidewruck

Hardware - Software - Net zwerke

Dynamisches SQL. Folien zum Datenbankpraktikum Wintersemester 2009/10 LMU München

Das SQL-Schlüsselwort ALL entspricht dem Allquantor der Prädikatenlogik

Kapitel 4 Die Datenbank Kuchenbestellung Seite 1

Version 1.0 [Wiederherstellung der Active Directory] Stand: Professionelle Datensicherung mit SafeUndSave.com. Beschreibung.

SQL - Übungen Bearbeitung der Datenbank Personal (1)

Hinweise zur Installation von MySQL

Informationen zum neuen Studmail häufige Fragen

Vielen Dank an Dennis Riehle für die Bereitstellung dieser Folien

Erstellen einer Collage. Zuerst ein leeres Dokument erzeugen, auf dem alle anderen Bilder zusammengefügt werden sollen (über [Datei] > [Neu])

Ein Hinweis vorab: Mailkonfiguration am Beispiel von Thunderbird

desk.modul : WaWi- Export

PHPNuke Quick & Dirty

UserManual. Handbuch zur Konfiguration einer FRITZ!Box. Autor: Version: Hansruedi Steiner 2.0, November 2014

LDAP Konfiguration nach einem Update auf Version 6.3 Version 1.2 Stand: 23. Januar 2012 Copyright MATESO GmbH

Kurzanleitung zur Erweiterung der htdig

TU München, Fakultät für Informatik Lehrstuhl III: Datenbanksysteme Prof. Alfons Kemper, Ph.D.

Welche Gedanken wir uns für die Erstellung einer Präsentation machen, sollen Ihnen die folgende Folien zeigen.

OP-LOG

Den Fehler session error bei der Kalenderanmeldung beheben:

Artikel Schnittstelle über CSV

IV. Datenbankmanagement

Internet online Update (Internet Explorer)

Wie Sie mit Mastern arbeiten

Referenzielle Integrität SQL

Handbuch Fischertechnik-Einzelteiltabelle V3.7.3

Jede Zahl muss dabei einzeln umgerechnet werden. Beginnen wir also ganz am Anfang mit der Zahl,192.

Kapitel 33. Der xml-datentyp. In diesem Kapitel: Der xml-datentyp 996 Abfragen aus xml-datentypen 1001 XML-Indizierung 1017 Zusammenfassung 1023

7. Übung - Datenbanken

AGROPLUS Buchhaltung. Daten-Server und Sicherheitskopie. Version vom b

Transkript:

1/40 PHP-User-Group Stuttgart 08.02.2012 Datenbank- und SQL-Performance Erkennen warum eine SQL-Abfrage langsam ist SQL Tipps und Tricks aus der Praxis

2/40 Wer Wer bin bin ich ich? Thomas Wiedmann n+1 Jahre Problemlösungen in der Softwareentwicklung Seit vielen Jahren Projekte mit PHP und Oracle PL/SQL bzw. DB2/NT Zend Certified PHP Engineer (ZCE) IBM Certified Solution Expert - DB2 UDB v7.1 Database Administration Autor diverser Fachartikel in der Toolbox und im PHP-Magazin Autor des Buches DB2 SQL, Programmierung, Tuning 2001 SQL-Tipps, MySQL-EXPLAIN und Performance in der SQL-Backstube

3/40 Überblick Datenbankperformance Was ist das? SQL Anti-Patterns Warum ist eine SQL-Abfrage eigentlich langsam? DISTINCT, RAND(), GROUP BY Vorsicht Falle! The End!

Datenbankperformance Was Was ist ist das? das? CREATE TABLE testdaten ( id INT NOT NULL, PRIMARY KEY (id) ); 4/40 ----------------------------------------------- Welche SQL-Abfrage ist schneller bzw. performanter? a) SELECT id FROM testdaten WHERE id LIKE '4711' b) SELECT id FROM testdaten WHERE id = 4711 c)

Datenbankperformance Was Was ist ist das? das? CREATE TABLE testdaten ( id INT NOT NULL, PRIMARY KEY (id) ); 5/40 ----------------------------------------------- Welche SQL-Abfrage ist schneller bzw. performanter? 3.) SELECT id FROM testdaten WHERE id LIKE '4711' Query opened in 0,362s [0,361s exec, 0,001s fetch] 2.) SELECT id FROM testdaten WHERE id = 4711 Query opened in 0,002s [0,001s exec, 0,001s fetch] 1.)

6/40 Datenbankperformance Datenbankperformance Was Was ist ist das? das? Datenbanken und SQL sind strongly typed! Query Optimization Theorie, Prioritäten und Basics: 1. Avoid the query = Vermeide die Abfrage! 2. Cache the query 3. Simplify the query 4. Optimize the query MySQL Queries Optimization: "Zitate von Peter Zaitsev, Percona (c) Zürich Fun tour November 21 2007"

SQL SQL Anti-Patterns Anti-Patterns Wie prüft man einen Login gegen eine SQL-Datenbank-Tabelle? 7/40 CREATE TABLE users ( user_id INT NOT NULL, name VARCHAR(50) NOT NULL, passwort VARCHAR(50) NOT NULL, PRIMARY KEY(user_id) ); Sollte eigentlich klar sein, aber PHP Programmierer waren schon immer sehr creativ... ACHTUNG!

SQL SQL Anti-Patterns Anti-Patterns Wie prüft man einen Login gegen eine SQL-Datenbank-Tabelle? 8/40 Gesehen in einem PHP-Forum, mit dem obligatorischen Hinweis...funzt nich.. <?php [...] $sqlbenutzername = 'SELECT name FROM users'; $sqlpasswort = 'SELECT passwort FROM users'; [...] while($dbbenutzer = mysql_fetch_row($sqlbenutzername)) while($dbpasswort = mysql_fetch_row($sqlpasswort)){ for($i = 0; $i < mysql_num_rows($sqlbenutzername); $i++) for($j = 0; $j < mysql_num_rows($sqlpasswort); $j++){ if($benutzername == $dbbenutzer and $pass == $dbpasswort){ echo '<p>sie haben sich erfolgreich angemeldet</p>'; echo '<a href="willkommen.html">willkommen</a>'; } } } } [...]?>

SQL SQL Anti-Patterns Anti-Patterns Wie prüft man einen Login gegen eine SQL-Datenbank-Tabelle? 9/40 Gesehen in einem PHP-Forum, mit dem obligatorischen Hinweis...funzt nich.. <?php [...] $sqlbenutzername = 'SELECT name FROM users'; $sqlpasswort = 'SELECT passwort FROM users'; [...] while($dbbenutzer = mysql_fetch_row($sqlbenutzername))..oder while($dbpasswort = mysql_fetch_row($sqlpasswort)){..oder vielleicht vielleicht doch doch eher eher so: so: for($i = 0; $i < mysql_num_rows($sqlbenutzername); $i++) for($j = 0; SELECT $j < mysql_num_rows($sqlpasswort); $j++){ SELECT COUNT(*) COUNT(*) FROM FROM users users if($benutzername WHERE == $dbbenutzer and $pass == $dbpasswort){ echo '<p>sie WHERE name haben name = sich erfolgreich :sname :sname angemeldet</p>'; echo '<a href="willkommen.html">willkommen</a>'; AND AND passwort passwort = :spasswort; } } } } [...]?>

SQL SQL Anti-Patterns Anti-Patterns Wie ermittelt man am Besten die Anzahl Datensätze dieser Tabelle? CREATE TABLE bigtable ( big_id BIGINT UNSIGNED NOT NULL,... PRIMARY KEY(big_id) ); 10/40 Sollte eigentlich klar sein, aber PHP Programmierer waren schon immer sehr creativ... ACHTUNG!

SQL SQL Anti-Patterns Anti-Patterns Wie ermittelt man am Besten die Anzahl Datensätze dieser Tabelle? Gesehen in einem PHP-Forum <?php [...] $result = mysql_query('select * FROM bigtable'); $adata = array(); while ($arow = mysql_fetch_array($result)) { $adata[] = $arow; } echo 'Anzahl Datensätze '.count($adata); [...]?> 11/40

SQL SQL Anti-Patterns Anti-Patterns Wie ermittelt man am Besten die Anzahl Datensätze dieser Tabelle? Gesehen in einem PHP-Forum <?php [...] $result = mysql_query('select * FROM bigtable'); $adata = array(); while ($arow = mysql_fetch_array($result)) {..oder $adata[] = $arow;..oder vielleicht vielleicht doch doch eher eher so: so: } SELECT SELECT COUNT(*) COUNT(*) FROM FROM bigtable; echo 'Anzahl Datensätze '.count($adata); [...]?> 12/40

SQL SQL Anti-Patterns Anti-Patterns Model/Aktive Record Problematik: 13/40 $akunde = Projekt_model_kunde::read($nKunde_id); if ($akunde['status']) { $nrechnung_id = (int) $_POST['nRechnung_id']; $arechnung = Projekt_model_rechnung::read($nRechnung_id); if ($arechnung['status']) { $arabatt = Projekt_model_rabatt::read($nRabatt_id); if ($arabatt['status']) {... u.s.w.... } } }

SQL SQL Anti-Patterns Anti-Patterns Model/Aktive Record Problematik: 14/40 $akunde = Projekt_model_kunde::read($nKunde_id); if ($akunde['status']) { } $nrechnung_id = (int) $_POST['nRechnung_id']; $arechnung = Projekt_model_rechnung::read($nRechnung_id); if ($arechnung['status']) { } $arabatt = Projekt_model_rabatt::read($nRabatt_id); if ($arabatt['status']) { }... u.s.w.... SELECT.. SELECT.. SELECT..

SQL SQL Anti-Patterns Anti-Patterns Model/Aktive Record Problematik: 15/40 $akunde = Projekt_model_kunde::read($nKunde_id); if ($akunde['status']) { } $nrechnung_id = (int) $_POST['nRechnung_id']; $arechnung = Projekt_model_rechnung::read($nRechnung_id); if ($arechnung['status']) { } $arabatt = Projekt_model_rabatt::read($nRabatt_id); if ($arabatt['status']) { }... u.s.w......oder..oder vielleicht vielleicht doch doch eher eher so: so: SELECT SELECT k.*, k.*, r.*, r.*, ra.* ra.* FROM FROM kunde kunde k JOIN JOIN rechnung rechnung r ON ON k.kunde_id r.kunde_id JOIN JOIN rabatt rabatt ra ra ON ON ra.rabbatt_id = WHERE WHERE SELECT.. SELECT.. SELECT..

16/40 SQL SQL Anti-Patterns Anti-Patterns Wesentliche Hinweise für gesundes SQL- und Datenbanken 1. Know-how 2. g'wusst wie 3. savoir-faire 4. know-how 5. SQL Backstube (http://www.twiedmann.de/sqlbackstube/feedrss20)

Was Was macht macht eine eine SQL-Abfrage SQL-Abfrage eigentlich eigentlich langsam? langsam? select t1.col1, t2.col2, count(t3.id) AS id from tabelle1 t1 join tabelle2 t2 on t2.id = t1.id join tabelle3 t3 on t3.id = t2.id where t2.col2 = 4711 and t1.col1 > 10 group by t1.col1, t2.col2 order by t3.id Limit 100000, 10; 17/40 Was soll'n das sein..?

Was Was macht macht eine eine SQL-Abfrage SQL-Abfrage eigentlich eigentlich langsam? langsam? SELECT t1.col1, t2.col2, COUNT(t3.id) AS id FROM tabelle1 t1 JOIN tabelle2 t2 ON t2.id = t1.id JOIN tabelle3 t3 ON t3.id = t2.id WHERE t2.col2 = 4711 AND t1.col1 > 10 GROUP BY t1.col1, t2.col2 ORDER BY t3.id LIMIT 100000,10; 18/40 SQL Formatter http://www.dpriver.com/pp/sqlformat.htm

Was Was macht macht eine eine SQL-Abfrage SQL-Abfrage eigentlich eigentlich langsam? langsam? SELECT t1.col1, t2.col2, COUNT(t3.id) AS id FROM tabelle1 t1 JOIN tabelle2 t2 ON t2.id = t1.id JOIN tabelle3 t3 ON t3.id = t2.id WHERE t2.col2 = 4711 AND t1.col1 > 10 GROUP BY t1.col1, t2.col2 ORDER BY t3.id LIMIT 100000,10; Index auf beide IDs?!? Index auf beide IDs?!? 19/40

Was Was macht macht eine eine SQL-Abfrage SQL-Abfrage eigentlich eigentlich langsam? langsam? SELECT t1.col1, t2.col2, COUNT(t3.id) AS id FROM tabelle1 t1 JOIN tabelle2 t2 ON t2.id = t1.id JOIN tabelle3 t3 ON t3.id = t2.id WHERE t2.col2 = 4711 AND t1.col1 > 10 GROUP BY t1.col1, t2.col2 ORDER BY t3.id LIMIT 100000,10; kein guter Index möglich!! Order nach anderer Spalte als GROUP?!? 20/40 Order muss komplett ausgeführt werden, dann der komplette Resultset durchsucht werden, um 10 Datensätze auszugeben?!?

21/40 Was Was macht macht eine eine SQL-Abfrage SQL-Abfrage eigentlich eigentlich langsam? langsam? Immer dann wenn Daten umsortiert oder durchsucht werden müssen (Tablescan), dauert es mal wieder länger. LIMIT 10000,10 meiden, besser Sub-Select wenn möglich. (Pagination via OFFSET -- inefficient. ) Grosser RAM und Hardwarepower bringt viel, aber auch mit fundiertem Performance-Know-How läßt sich sehr gutes SQL-Tuning erreichen. MySQL ab 5.6.3 rüstet auf und spendiert der neuen Version einige Lösungen zu den oben genannten Problemen: Verbesserungen an MySQLs Optimierer (http://heise.de/-1354352 und http://blogs.oracle.com/mysql/entry/more_early_access_features_in)

Was Was macht macht eigentlich eigentlich DISTINCT? DISTINCT? CREATE TABLE rechnung ( rechnung_id INT NOT NULL, kunde_id INT NOT NULL, PRIMARY KEY(rechnung_id) ); 22/40 INSERT INTO rechnung VALUES ( 1, 10), (2, 10), (3, 20), (4, 20); SELECT DISTINCT * FROM rechnung; DISTINCT wird gerne verwendet, wenn in einem JOIN blöder weise doppelte Datensätze raus kommen, man nicht versteht warum und nun irgendwie das Ergebnis platt klopfen möchte. ABER...

Was Was macht macht eigentlich eigentlich DISTINCT? DISTINCT? SELECT DISTINCT * FROM rechnung; +-------------+----------+ rechnung_id kunde_id +-------------+----------+ 1 10 2 10 3 20 4 20 +-------------+----------+ 4 rows in set (0.00 sec) mehr Rechenaufwand aber gleiches Ergebnis wie SELECT *.. 23/40 SELECT * FROM rechnung; +-------------+----------+ rechnung_id kunde_id +-------------+----------+ 1 10 2 10 3 20 4 20 +-------------+----------+ 4 rows in set (0.00 sec) Wenn ein Primary Key oder eine andere eindeutige Spalte im DISTINCT enthalten ist, kann dieser die Daten nicht weiter verdichten. MySQL führt den DISTINCT aber trotzdem aus.

Was Was macht macht eigentlich eigentlich DISTINCT? DISTINCT? 24/40 SELECT COUNT(*) FROM testdaten; +----------+ COUNT(*) +----------+ 1000000 +----------+ 1 row in set (0.34 sec) Bei größeren Datenmengen ist DISTINCT richtig zeitaufwändig. (Test mit MySQL v.5.5.9) SELECT DISTINCT * FROM testdaten; [...] 100000000 4294967295 4294967295 +-------------+------------+------------+ 1000000 rows in set (15.73 sec) SELECT * FROM testdaten; [...] 100000000 4294967295 4294967295 +-------------+------------+------------+ 1000000 rows in set (0.75 sec)

Was Was macht macht eigentlich eigentlich DISTINCT? DISTINCT? 25/40 SELECT DISTINCT * FROM rechnung;..ist identisch zu... SELECT * FROM rechnung GROUP BY rechnung_id, kunde_id; +-------------+----------+ rechnung_id kunde_id +-------------+----------+ 1 10 2 10 3 20 4 20 +-------------+----------+ 4 rows in set (0.00 sec) DISTINCT ist identisch mit einem GROUP BY über alle beteiligten Spalten

26/40 Was Was macht macht eigentlich eigentlich DISTINCT? DISTINCT? Mit DISTINCT werden identische Daten(-sätze) eliminiert. Dabei kommt intern GROUP BY zum Einsatz. Sinnvolle Beispiele wären: SELECT DISTINCT col2, col3 FROM tabelle1; SELECT COUNT(DISTINCT col4) FROM tabelle1; Wenig sinnvolle Beispiele wären: SELECT DISTINCT * FROM tabelle1; SELECT DISTINCT meine_pk_id FROM tabelle1;

Zufälligen Zufälligen Datensatz Datensatz auswählen auswählen mit mit RAND()? RAND()? In vielen Online-Shops etc. sollen dem Besucher immer wieder zufällige Artikel oder Waren aus einem Pool von bestimmten Top-Artikel angeboten werden. Dafür finden sich viele Lösungsansätze, wie z. B. SELECT * FROM testdaten ORDER BY RAND() LIMIT 1; RAND() ist nicht als perfekter Zufallsgenerator gedacht, sondern stellt eine gute Möglichkeit dar, ad hoc Zufallszahlen zu Funktionen für die Benutzung in SELECT- und WHERE Klauseln zu erzeugen, die innerhalb derselben MySQL-Version plattformübergreifend funktionieren. MySQL Handbuch 27/40 Aber...

Zufälligen Zufälligen Datensatz Datensatz auswählen auswählen mit mit RAND()? RAND()? 28/40 Aber Vorsicht: Bei einer großen Datenmenge (1 Mio. Sätze) dauert diese Abfrage schon so seine Zeit und allgemein länger als man glaubt. SELECT * FROM testdaten ORDER BY RAND() LIMIT 1; Query opened in 0,721s [0,717s exec, 0,004s fetch] Es empfiehlt sich also unbedingt, den RAND() über eine kleine "Schlüssel" Tabelle laufen zu lassen. In einem 2. Schritt damit die zufällige ID zu ermitteln und erst mit dieser gefundenen ID den kompletten Datensatz zu lesen.

Zufälligen Zufälligen Datensatz Datensatz auswählen auswählen mit mit RAND()? RAND()? 29/40 RAND() ist zusammen mit ORDER BY eine MySQL-Speziallösung SELECT * FROM testdaten ORDER BY RAND() LIMIT 1; +-------------+------------+------------+ 86131500 4294967295 4294967295 +-------------+------------+------------+ SELECT RAND(); +---------------------+ 0.745993050510057 +---------------------+ SELECT * FROM testdaten ORDER BY 0.745993050510057 LIMIT 1; +-------------+----------+-----------+ 100 11100 22200 <== 1. Row der Tabelle +-------------+----------+-----------+

Zufälligen Zufälligen Datensatz Datensatz auswählen auswählen mit mit RAND()? RAND()? 30/40 RAND() ist zusammen mit ORDER BY eine MySQL-Speziallösung SELECT * FROM testdaten ORDER BY 0.2 LIMIT 1; +-------------+----------+-----------+ 100 11100 22200 +-------------+----------+-----------+ SELECT * FROM testdaten ORDER BY 0 LIMIT 1; ERROR 1054 (42S22): Unknown column '0' in 'order clause' SELECT * FROM testdaten ORDER BY 1 LIMIT 1; +-------------+----------+-----------+ 100 11100 22200 +-------------+----------+-----------+ SQL-Standard: Es wird die Spaltenposition aus der SELECT-Liste angegeben, nach der sortiert werde soll

Zufälligen Zufälligen Datensatz Datensatz auswählen auswählen mit mit RAND()? RAND()? 31/40 Übliche MySQL Lösung SELECT * FROM testdaten ORDER BY RAND() LIMIT 1; Query opened in 0,721s [0,717s exec, 0,004s fetch] Einfache Alternativlösung (geringfügig schneller) SELECT col1, col2, col3, RAND() FROM testdaten ORDER BY 4 LIMIT 1; Query opened in 0,673s [0,672s exec, 0,001s fetch]

Zufälligen Zufälligen Datensatz Datensatz auswählen auswählen mit mit RAND()? RAND()? 32/40 Mein Lösungvorschlag: Funktioniert auch wenn die ID nicht lückenlos ist. SELECT t.* FROM testdaten t JOIN ( SELECT FLOOR( MIN(id) + RAND() * MAX(id) +1 ) AS id FROM testdaten ) t ON g.id BETWEEN t.id AND t.id + 200 LIMIT 1; Query opened in 0,268s [0,267s exec, 0,001s fetch] Diese Abfrage ermittelt via SUB-Select zuerst einen kleinen zufälligen ID-Bereich und erst dann wird der komplette Datensatz gelesen. Dies braucht mit 0,268 Sekunden nur ein 1/3 der Zeit.

33/40 Zufälligen Zufälligen Datensatz Datensatz auswählen auswählen mit mit RAND()? RAND()? Mit ORDER BY RAND() liefert MySQL eine spezielle Syntax, um einen zufälligen Datensatz zu finden. Aber Vorsicht, um damit eine performante Abfrage zu erreichen, sollten möglichst nur wenige Datensätze im Spiel sein. Es lohnt sich also eine spezielle kleine ARTIKEL POOL Tabelle zu erstellen und nur darüber den ORDER BY RAND() auszuführen.

Zufälligen Zufälligen Lagerbestand Lagerbestand ermitteln ermitteln mit mit GROUP GROUP BY? BY? Zufällige Datensätze zu ermitteln kann erwünscht sein, aber einen zufälligen Lagerbestand zu berechnen ist eher nicht erwünscht. Hierzu ein tückisches Beispiel aus einem MySQL Forum! CREATE TABLE artikel ( artikel_id INT NOT NULL, bezeichnung VARCHAR(20) NOT NULL, gruppe_id INT NOT NULL, PRIMARY KEY (artikel_id) ); CREATE TABLE artikel_lager ( lager_id INT NOT NULL, artikel_id INT NOT NULL, menge DEC(10,2) NOT NULL, PRIMARY KEY (lager_id), CONSTRAINT fk_artikel_lager FOREIGN KEY (artikel_id) REFERENCES artikel (artikel_id) ); 34/40

Zufälligen Zufälligen Lagerbestand Lagerbestand ermitteln ermitteln mit mit GROUP GROUP BY? BY? Nun noch den Datenbestand einfügen und korrekt berechnen. 35/40 INSERT INTO artikel VALUES ( 1, 'Druckerpapier', 1), ( 2, 'Toner', 2), ( 3, 'Briefumschlag', 1); INSERT INTO artikel_lager VALUES ( 1, 1, 10 ), ( 2, 2, 20 ), ( 3, 3, 30 ), ( 4, 1, 10 ), ( 5, 2, 20 ), ( 6, 3, 30 ), ( 7, 1, 10 ), ( 8, 2, 20 ), ( 9, 3, 30 ); +-----------+-----------+ gruppe_id auf_lager +-----------+-----------+ 1 120.00 2 60.00 +-----------+-----------+ 2 rows in set (0.00 sec)

Zufälligen Zufälligen Lagerbestand Lagerbestand ermitteln ermitteln mit mit GROUP GROUP BY? BY? 36/40 Hierzu folgende Abfrage Was läuft hier falsch? SELECT a.gruppe_id, ( SELECT SUM(l.menge) FROM artikel_lager l WHERE l.artikel_id = a.artikel_id ) AS auf_lager FROM artikel a GROUP BY a.gruppe_id ORDER BY a.gruppe_id; +-----------+-----------+ gruppe_id auf_lager +-----------+-----------+ 1 30.00 <== sollten 120 (?) 2 60.00 +-----------+-----------+ 2 rows in set (0.00 sec)

Zufälligen Zufälligen Lagerbestand Lagerbestand ermitteln ermitteln mit mit GROUP GROUP BY? BY? 37/40 Hierzu folgende Abfrage Was läuft hier falsch? - GROUP BY!! SELECT a.gruppe_id, SUM( ( SELECT SUM(l.menge) FROM artikel_lager l WHERE l.artikel_id = a.artikel_id ) ) AS auf_lager FROM artikel a GROUP BY a.gruppe_id ORDER BY a.gruppe_id; +-----------+-----------+ gruppe_id auf_lager +-----------+-----------+ 1 120.00 2 60.00 +-----------+-----------+ 2 rows in set (0.00 sec)

38/40 MySQL MySQL - - SQL SQL Modus Modus und und GROUP GROUP BY BY Möglichkeiten MySQL zu zwingen eher ANSI-SQL zu verarbeiten. (durch Anpassen des SQL-Modus des Servers) ONLY_FULL_GROUP_BY Nur Spalten der GROUP BY-Klausel dürfen direkt in der Select-Liste stehen. Für alle anderen müssen Aggregatfunktionen wie MIN(), MAX(), COUNT(), SUM() etc. angewendet werden. ANSI Ändert Syntax und Verhalten so, dass eine höhere Kompatibilität mit Standard-SQL erzielt wird. ANSI enthält folgende Modi: REAL_AS_FLOAT, PIPES_AS_CONCAT, ANSI_QUOTES, IGNORE_SPACE mehr Details dazu siehe 5.2.5. Der SQL-Modus des Servers

39/40 GROUP BY und SQL-Standard MySQL MySQL - - SQL SQL Modus Modus und und GROUP GROUP BY BY MySQL erlaubt falsche GROUP BY Konstruktionen http://dev.mysql.com/doc/refman/5.0/en/group-by-hidden-columns.html SELECT @@global.sql_mode; liefert den Server SQL-Modus SELECT @@session.sql_mode; liefert den session SQL-Modus sql_mode = 'ONLY_FULL_GROUP_BY' kennen und nutzen Mehr zu Server-Modus siehe 5.2.5. Der SQL-Modus des Servers

40/40 GROUP BY und SQL-Standard MySQL MySQL - - SQL SQL Modus Modus und und GROUP GROUP BY BY MySQL erlaubt falsche GROUP BY Konstruktionen http://dev.mysql.com/doc/refman/5.0/en/group-by-hidden-columns.html The End! SELECT @@global.sql_mode; liefert den Server SQL-Modus SELECT @@session.sql_mode; liefert den session SQL-Modus sql_mode = 'ONLY_FULL_GROUP_BY' kennen und nutzen Mehr zu Server-Modus siehe 5.2.5. Der SQL-Modus des Servers