php-resource



Zurück   PHP-Scripte PHP-Tutorials PHP-Jobs und vieles mehr > Entwicklung > SQL / Datenbanken
 

Login

 
eingeloggt bleiben
star Jetzt registrieren   star Passwort vergessen
 

 

 


SQL / Datenbanken Probleme mit SQL? Hier könnt ihr eure Fragen zu SQL (MySQL, PostgreSQL, MS-SQL und andere ANSI-SQL Server) los werden.

Antwort
 
LinkBack Themen-Optionen Thema bewerten
  #1 (permalink)  
Alt 18-11-2009, 16:11
prego
 PHP Senior
Links : Onlinestatus : prego ist offline
Registriert seit: May 2005
Ort: Herborn
Beiträge: 1.609
prego ist zur Zeit noch ein unbeschriebenes Blatt
Standard LEFT JOIN ohne JOIN

Hi,

ich komme wieder mal mit einem Problem zu euch was ich alleine nicht lösen kann.

Situation: 2 Tabellen, eine Tabelle schließt die andere Tabelle aus.

Code:
SELECT 
t1.wert 

FROM 
tab1 t1

LEFT JOIN tab2 t2
ON t2.wert = t1.wert

WHERE 
t2.wert IS NULL
Da nun aber leider diese Art Query auf unserem NDB Cluster ca 600ms benötigt sind wir dazu über gegangen das ganze in "alter" Notation zu schreiben:
Code:
SELECT 
t1.wert 

FROM tab1 t1, tab2 t2

WHERE 
t1.wert = t2.wert
Was komischerweise schneller ist... zumindest bei normalen joins.

Nun meine Frage: Wie kann ich in der "alten" Noatation einen LEFT JOIN abbilden?

Dank euch schonmal
Mit Zitat antworten
  #2 (permalink)  
Alt 18-11-2009, 16:21
AmicaNoctis
  Moderatorin
Links : Onlinestatus : AmicaNoctis ist offline
Registriert seit: Jul 2009
Beiträge: 5.709
Blog-Einträge: 9
AmicaNoctis sorgt für eine eindrucksvolle AtmosphäreAmicaNoctis sorgt für eine eindrucksvolle Atmosphäre
Standard

Hallo,

die "alte" Notation ist ein Cross Join (der durch die Where-Klausel sowas wie ein Inner Join wird) und damit etwas ganz anderes als ein Left (Outer) Join ist. Es gibt also keine sinnvolle Möglichkeit, einen Left Join mit einem Cross Join nachzubauen (es würde mit Union und einer auf Null-Werte angepassten Where-Klausel gehen, was aber noch unperformanter ist)

Wenn auf dem System der Left Join deiner Meinung nach zu langsam ist, kannst du es ja mal mit einem Right Join probieren und die Tabellen andersrum referenzieren.

Edit: hast du einen Index auf die Spalte wert? Wenn nicht, ist das der Grund dafür, dass es so langsam ist.

Gruß,

Amica

Geändert von AmicaNoctis (18-11-2009 um 16:23 Uhr)
Mit Zitat antworten
  #3 (permalink)  
Alt 18-11-2009, 16:21
h3ll
 Registrierter Benutzer
Links : Onlinestatus : h3ll ist offline
Registriert seit: Mar 2008
Beiträge: 3.576
h3ll befindet sich auf einem aufstrebenden Ast
Standard

Zitat:
Zitat von prego Beitrag anzeigen
Hi,

ich komme wieder mal mit einem Problem zu euch was ich alleine nicht lösen kann.

Situation: 2 Tabellen, eine Tabelle schließt die andere Tabelle aus.

Code:
SELECT 
t1.wert 

FROM 
tab1 t1

LEFT JOIN tab2 t2
ON t2.wert = t1.wert

WHERE 
t2.wert IS NULL
Da nun aber leider diese Art Query auf unserem NDB Cluster ca 600ms benötigt sind wir dazu über gegangen das ganze in "alter" Notation zu schreiben:
Code:
SELECT 
t1.wert 

FROM tab1 t1, tab2 t2

WHERE 
t1.wert = t2.wert
Was komischerweise schneller ist... zumindest bei normalen joins.

Nun meine Frage: Wie kann ich in der "alten" Noatation einen LEFT JOIN abbilden?

Dank euch schonmal
Das erste ist ein LEFT JOIN, das zweite ein INNER JOIN (mit fürchterlicher Theta-Style Schreibweise). INNER JOINs sind gewöhnlich schneller als LEFT JOINs, hat also nix mit deiner Schreibweise zu tun.
Mit Zitat antworten
  #4 (permalink)  
Alt 18-11-2009, 16:29
prego
 PHP Senior
Links : Onlinestatus : prego ist offline
Registriert seit: May 2005
Ort: Herborn
Beiträge: 1.609
prego ist zur Zeit noch ein unbeschriebenes Blatt
Standard

Ich dachte es mir fast das es nicht funktioniert in dieser Schreibweise. Dummes NDB

Indizes sind gesetzt und werden laut explain auch benutzt.

Ich mach es jetzt so das ich erst alle Werte aus tab1 selecte und danach in php die Werte aus tab2 aus dem Ergebnisarray entferne. Danach noch ein array_slice zum blättern da ich ja limit nicht verwenden kann.

Macht das ganze in 120ms, im Gegensatz zu ca. 700ms des left joins. SQL_CACHE_SELECT hilft leider nicht da es sich um eine Statistiktabelle handelt wie recht häuft einen Insert bekommt.

Danke euch trotzdem allen.
Mit Zitat antworten
  #5 (permalink)  
Alt 18-11-2009, 16:31
h3ll
 Registrierter Benutzer
Links : Onlinestatus : h3ll ist offline
Registriert seit: Mar 2008
Beiträge: 3.576
h3ll befindet sich auf einem aufstrebenden Ast
Standard

Zitat:
Zitat von prego Beitrag anzeigen
Ich dachte es mir fast das es nicht funktioniert in dieser Schreibweise. Dummes NDB

Indizes sind gesetzt und werden laut explain auch benutzt.

Ich mach es jetzt so das ich erst alle Werte aus tab1 selecte und danach in php die Werte aus tab2 aus dem Ergebnisarray entferne. Danach noch ein array_slice zum blättern da ich ja limit nicht verwenden kann.

Macht das ganze in 120ms, im Gegensatz zu ca. 700ms des left joins. SQL_CACHE_SELECT hilft leider nicht da es sich um eine Statistiktabelle handelt wie recht häuft einen Insert bekommt.

Danke euch trotzdem allen.
Dann schau dir doch mit EXPLAIN an, wo der Flaschenhals ist.

MySQL :: MySQL 5.1 Referenzhandbuch :: 7.2.1 EXPLAIN-Syntax (Informationen über ein SELECT erhalten)
Mit Zitat antworten
  #6 (permalink)  
Alt 18-11-2009, 17:28
prego
 PHP Senior
Links : Onlinestatus : prego ist offline
Registriert seit: May 2005
Ort: Herborn
Beiträge: 1.609
prego ist zur Zeit noch ein unbeschriebenes Blatt
Standard

Code:
EXPLAIN SELECT SQL_CALC_FOUND_ROWS 

t1.wert

FROM 
tab1 t1 

LEFT JOIN tab2 t 2
ON t1.wert = t2.wert

WHERE 
DATE_SUB(curdate(), interval 30 day) < t1.day AND 
t2.wert IS NULL 

GROUP BY t1.wert

ORDER BY t1.wert 

LIMIT 0,150
ergibt:

(sorry fürs scrollen)
Code:
+----+-------------+-------+--------+---------------+---------+---------+----------------+------+--------------------------------------------------------------------+
| id | select_type | table | type   | possible_keys | key     | key_len | ref            | rows | Extra                                                              |
+----+-------------+-------+--------+---------------+---------+---------+----------------+------+--------------------------------------------------------------------+
|  1 | SIMPLE      | t1    | range  | day           | day     | 3       | NULL           |   10 | Using where with pushed condition; Using temporary; Using filesort |
|  1 | SIMPLE      | t2    | eq_ref | PRIMARY       | PRIMARY | 130     | t2.wert        |    1 | Using where; Not exists                                            |
+----+-------------+-------+--------+---------------+---------+---------+----------------+------+--------------------------------------------------------------------+

Hmm, mit pushed condition kann ich leider nichts anfangen. t1.day hat einen eigenstehenden index. Der PrimaryKey setzt sich aus drei Spalten zusammen von denen day auch einen ist. In t2 ist wert der Primärschlüssel. Sonst keine.
Mit Zitat antworten
  #7 (permalink)  
Alt 18-11-2009, 18:25
TBT
  Moderator
Links : Onlinestatus : TBT ist offline
Registriert seit: Sep 2002
Ort: Berlin
Beiträge: 2.787
TBT befindet sich auf einem aufstrebenden Ast
TBT eine Nachricht über ICQ schicken TBT eine Nachricht über AIM schicken TBT eine Nachricht über Yahoo! schicken
Standard

dreh mal die Berechnung um, die Spalte Berechnen, nicht die Konstante curdate

hier => DATE_SUB(curdate(), interval 30 day) < t1.day

außerdem ist der Index nicht richtig korrekt, wenn er filesort und temporary nutzt
__________________
TBT

Die zwei wichtigsten Regeln für eine berufliche Karriere:
1. Verrate niemals alles was du weißt!


PHP 2 AllPatrizier II Browsergame
Mit Zitat antworten
  #8 (permalink)  
Alt 18-11-2009, 18:28
AmicaNoctis
  Moderatorin
Links : Onlinestatus : AmicaNoctis ist offline
Registriert seit: Jul 2009
Beiträge: 5.709
Blog-Einträge: 9
AmicaNoctis sorgt für eine eindrucksvolle AtmosphäreAmicaNoctis sorgt für eine eindrucksvolle Atmosphäre
Standard

Zitat:
Zitat von TBT Beitrag anzeigen
dreh mal die Berechnung um, die Spalte Berechnen, nicht die Konstante curdate
Warum? Erstens ist curdate keine Konstante, sondern eine Funktion und zweitens kann das DBMS diese Berechnung cachen, was es nicht könnte, wenn man die Spalte berechnen würde. Finde die Variante des TO daher auch sinnvoll. Wenn du das anders siehst, wäre ich an Belegen dafür interessiert.
Mit Zitat antworten
  #9 (permalink)  
Alt 18-11-2009, 18:39
h3ll
 Registrierter Benutzer
Links : Onlinestatus : h3ll ist offline
Registriert seit: Mar 2008
Beiträge: 3.576
h3ll befindet sich auf einem aufstrebenden Ast
Standard

Zitat:
Zitat von AmicaNoctis Beitrag anzeigen
Warum? Erstens ist curdate keine Konstante, sondern eine Funktion und zweitens kann das DBMS diese Berechnung cachen, was es nicht könnte, wenn man die Spalte berechnen würde.
Der MySQL Query Cache greift nicht bei variablen Werten wie NOW(), CURRENT_DATE(), usw.

Deshalb sollte man Datum und Zeit wenn möglich als String übergeben um die beste Leistung zu erzielen.
Mit Zitat antworten
  #10 (permalink)  
Alt 18-11-2009, 18:44
AmicaNoctis
  Moderatorin
Links : Onlinestatus : AmicaNoctis ist offline
Registriert seit: Jul 2009
Beiträge: 5.709
Blog-Einträge: 9
AmicaNoctis sorgt für eine eindrucksvolle AtmosphäreAmicaNoctis sorgt für eine eindrucksvolle Atmosphäre
Standard

Ok, stimmt, trotzdem gehört meiner Meinung nach die Berechnung auf die Seite der Nichtspalte, sofern das möglich ist. Also z. B.

Code:
set @date = curdate();
select * from t1
where @date - interval 30 day < t1.day;
Ok, das Beispiel hinkt etwas, weil man die Berechnung dann ja gleich mit in die Zuweisung übernehmen könnte.
Mit Zitat antworten
  #11 (permalink)  
Alt 19-11-2009, 11:21
prego
 PHP Senior
Links : Onlinestatus : prego ist offline
Registriert seit: May 2005
Ort: Herborn
Beiträge: 1.609
prego ist zur Zeit noch ein unbeschriebenes Blatt
Standard

Hi,

das Datum übergebe ich mittlerweile komplett als String: '2009-10-19' < t1.day - fällt also aus


Zitat:
Zitat von TBT Beitrag anzeigen
außerdem ist der Index nicht richtig korrekt, wenn er filesort und temporary nutzt
Das hier würde mich interessieren.

Es wird t1.wert gegrouped und geordered, t1.wert ist teil des primary key's. Aber, explain beschwert sicht ja garnicht über t1.wert sondern über t1.day und selbst da benutzt er den vorhanden Index.

t2.wert ist einzige Spalte im primary key von t2.

Wo fehlt denn der Index oder wo ist er denn falsch? Ich steig noch nicht ganz durch.
Mit Zitat antworten
Antwort

Lesezeichen


Aktive Benutzer in diesem Thema: 1 (Registrierte Benutzer: 0, Gäste: 1)
 

Ähnliche Themen
Thema Autor Forum Antworten Letzter Beitrag
Left Join Seikilos SQL / Datenbanken 5 12-04-2009 09:43
[LEFT JOIN] Weiteres Left Join Anhängen mit Sortierfunktion Laire SQL / Datenbanken 3 11-01-2008 09:38
left join tsaenger SQL / Datenbanken 1 19-10-2003 19:42
left join Kropff SQL / Datenbanken 3 26-05-2002 00:13
left Join PAB SQL / Datenbanken 1 05-01-2001 16:36

Themen-Optionen
Thema bewerten
Thema bewerten:

Forumregeln
Es ist Ihnen nicht erlaubt, neue Themen zu verfassen.
Es ist Ihnen nicht erlaubt, auf Beiträge zu antworten.
Es ist Ihnen nicht erlaubt, Anhänge hochzuladen.
Es ist Ihnen nicht erlaubt, Ihre Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are an


PHP News

ebiz-trader 7.5.0 mit PHP7 Unterstützung veröffentlicht
ebiz-trader 7.5.0 mit PHP7 Unterstützung veröffentlichtDie bekannte Marktplatzsoftware ebiz-trader ist in der Version 7.5.0 veröffentlicht worden.

28.05.2018 | Berni

Wissensbestand in Unternehmen
Wissensbestand in UnternehmenLebenslanges Lernen und Weiterbilden sichert Wissensbestand in Unternehmen

25.05.2018 | Berni


 

Aktuelle PHP Scripte

PHP Server Monitor

PHP Server Monitor ist ein Skript, das prüft, ob Ihre Websites und Server betriebsbereit sind.

11.09.2018 Berni | Kategorie: PHP/ Security
PHP WEB STATISTIK ansehen PHP WEB STATISTIK

Die PHP Web Statistik bietet Ihnen ein einfach zu konfigurierendes Script zur Aufzeichnung und grafischen und textuellen Auswertung der Besuchern Ihrer Webseite. Folgende zeitlichen Module sind verfügbar: Jahr, Monat, Tag, Wochentag, Stunde Folgende son

28.08.2018 phpwebstat | Kategorie: PHP/ Counter
Affilinator - Affilinet XML Produktlisten Skript

Die Affilinator Affilinet XML Edition ist ein vollautomatisches Skript zum einlesen und darstellen der Affili.net (Partnerprogramm Netzwerk) Produktlisten und Produktdaten. Im Grunde gibt der Webmaster seine Affilinet PartnerID ein und hat dann unmittelb

27.08.2018 freefrank@ | Kategorie: PHP/ Partnerprogramme
 Alle PHP Scripte anzeigen

Alle Zeitangaben in WEZ +2. Es ist jetzt 00:32 Uhr.