Abbruch bei Vergleich

heikomi

Erfahrenes Mitglied
Hi,
ich möchte nichtbenötigte Datensätze aus einer Tabelle (1) löschen. Leider bricht MySQL immer wieder ab.

Tabelle 1: Anzahl DS in tmp_sort ca. 10.000 (Spieler der 1. Bundesliga)
Tabelle 2: Anzahl DS in tmp_24 ca. 40.000 (Aufgebote der 1. Bundesliga)

Kann man diese Routine beschleunigen

PHP:
$query = "select DBNr, DSId, Zusatz from tmp_sort WHERE DBNr = '$aktDB' AND Zusatz = 'j' ";
$ergebnis = mysql_query($query) or die (mysql_error());
while ($row = mysql_fetch_array($ergebnis)) {
  $Tmp_ID = $row['DSId'];
  $query2 = "select SpielerIDold from tmp_db18 WHERE SpielerIDold = '$Tmp_ID' ";
  $ergebnis2 = mysql_query($query2) or die (mysql_error());
  
  if(mysql_num_rows($ergebnis2) > 0){
    mysql_query("UPDATE tmp_sort SET Zusatz = 'n' WHERE DBNr = '$aktDB' AND DSId = '$Tmp_ID' ");
  }
}
echo "<b>unbenutzte gefunden</b><br>";

Danke für Eure Hilfe

Gruss aus Sachsen-Anhalt
 
Wenn ich Dein Problem richtig verstanden habe, solltest Du alle zu ändernden Datensätze mit folgendem Query erhalten:
Code:
select DSId
from tmp_sort
left join tmp_db18
  on tmp_db18.SpielerIDold=tmp_sort.DSId
where tmp_db18.SpielerIDold is null
  and tmp_sort.DBNr='$aktDB'
  and tmp_sort.Zusatz='j'
Damit benötigst Du das Query innerhalb der while-Schleife nicht mehr. Üblicherweise kann man sagen, dass es Performance kostet, je mehr einzelne Queries man absetzt.
Um Dir auch die vielen Update-Queries zu ersparen, würde ich folgendes vorschlagen:
PHP:
$res=mysql_query(/*Das Query von oben*/);
$arr=array();
while ($row=mysql_fetch_assoc($res)) {
    $arr[]=$row['DSId'];
}
$inString=implode(",",$arr);
mysql_query("UPDATE tmp_sort SET 
      Zusatz = 'n' 
    WHERE DBNr = '$aktDB' 
      AND DSId IN ($inString)");
Probier das aber bitte nicht gleich an den richtigen Daten aus, schließlich konnte ich das nicht testen.

Gruß hpvw
 
hi hpvw,
nein, ich werd es nicht an den Originallen Daten testen.

Ich werd es später aber dennoch testen. Es ist eine komplette Datenreorganisation.

Danke dir aber schon mal.

Gruss aus Sachsen-Anhalt



Nein hpvw,
führt auch nicht zum gewünschten Ergebniss.
Übrigens es gibt keine Nullwerte und jeder DS hat eine ID. Es ist aber so, das in der Tabelle 1 Spielerdaten vorhanden sind, die nie gespielt haben und die sollen entfernt werden.

Gruss
 
Zuletzt bearbeitet:
Ups, sorry, Du hast recht, so kann es nicht funktionieren. So schon eher:
Code:
select DSId
from tmp_sort
left join tmp_db18
  on tmp_db18.SpielerIDold=tmp_sort.DSId
    and tmp_sort.DBNr='$aktDB'
    and tmp_sort.Zusatz='j'
where tmp_db18.SpielerIDold is null
So, wie ich es mir eben schon vorgestellt habe, sollten die NULL-Werte nun durch das LEFT JOIN entstehen, wenn es keine passenden Datensätze gibt.

Gruß hpvw

EDIT: Läuft das Skript denn auf diese Weise wenigstens durch? Sonst müßte man an dem Ansatz gar nicht weiter probieren, selbst, wenn man damit noch zu einer Lösung findet.
 
Zuletzt bearbeitet:
Hi, hpvw
nein auch das bricht ab (HTTP Error: 500)

Mal so erklärt:
In der Tabelle tmp_sort sind alle IDs von allen vorhandenen Spielern gespeichert (DSId) und der Zusatz 'j' für angenommen hat mal gespielt.

In der Tabelle tmp_db18 sind alle Aufgebote (nicht wie oben angegeben 40.000 sondern 740.000)

Er soll jetzt in allen Aufgeboten die Spieler, die nicht gespielt haben, finden und in der Tabelle tmp_sort den Zusatz auf 'n' ändern.

Ich denk mal, dass ich die Routine komplett ändern werden muss und die Saisons einzeln durchlaufen werde. Dauert zwar auch aber das ganze ist ja nur local und kann über Nacht mal geschehen.

Gruss aus Sachsen-Anhalt
 
Hallo,
ich habe mal ein kleines Beispiel gemacht, was in Ansätzen Deinem Problem entspricht.
Natürlich habe ich nicht so viele Testdaten eingefügt, wie Du in Deiner Tabelle hast. Da würde ich den Überblick verlieren. Es ist jedoch ein anderer Ansatz, der evtl. schneller ausgeführt werden kann. Bei 740.000 Datensätzen würde es mich jedoch nicht wundern, wenn auch diese Variante zu lange dauert. Mit dem Command-Line-Client solltest Du diese Beschränkungen nicht haben, so dass die Queries auch vollständig ausgeführt werden können.
Ich hoffe, Du hast einen Index auf den entsprechenden Feldern, da ein Index die Abfragen wesentlich beschleunigt.

Mein Beispiel hat zwei Tabellen. In der deltestMain steht nur eine id. Diese Tabelle entspricht Deiner Tabelle tmp_sort, die id entspricht Deiner DSId.
Die zweite Tabelle deltestForeign beinhaltet eine id als Primärschlüssel und ein Feld namens fk, welches die Verknüpfung zur deltestMain herstellt. Die Tabelle entspricht Deiner tmp_db18, das Feld fk Deinem Feld SpielerIDold.

Ich habe eine temporäre Tabelle mit den fk-Werten aus der zweiten Tabelle (mit distinct) angelegt, dann lösche ich mit NOT IN aus der ersten Tabelle.

Wenn ich Dein Problem richtig interpretiere führt dieser Weg zum richtigen Ergebnis. Bleibt die Frage, ob es bei Deiner Datenflut schnell genug ist.

Ich hoffe nach den Worten genügt es, wenn ich Dir einfach den Auszug aus dem Command-Line-Client zeige:
Code:
mysql> select * from deltestMain;
+----+
| id |
+----+
|  1 |
|  2 |
|  3 |
|  4 |
|  5 |
+----+
5 rows in set (0.00 sec)

mysql> select * from deltestForeign;
+----+----+
| id | fk |
+----+----+
|  1 |  1 |
|  2 |  3 |
|  3 |  1 |
|  4 |  4 |
|  5 |  5 |
|  6 |  3 |
+----+----+
6 rows in set (0.00 sec)

mysql> create temporary table dontDel
    ->   select distinct fk from deltestForeign;
Query OK, 4 rows affected (0.16 sec)
Records: 4  Duplicates: 0  Warnings: 0

mysql> select * from dontDel;
+----+
| fk |
+----+
|  1 |
|  3 |
|  4 |
|  5 |
+----+
4 rows in set (0.00 sec)

mysql> delete from deltestMain where id not in (
    -> select fk from dontDel);
Query OK, 1 row affected (0.06 sec)

mysql> select * from deltestMain;
+----+
| id |
+----+
|  1 |
|  3 |
|  4 |
|  5 |
+----+
4 rows in set (0.00 sec)
Wie Du siehst, habe ich die Datensätze gleich gelöscht. Du kannst an der Stelle natürlich auch ein Update mit der Bedingung machen. Mir fehlte das passende Feld für ein Update :-(

Gruß hpvw
 
vielen Dank hpvw, man kommt der Lösung wirklich näher, es gibt nur noch einen Fehler.

Dein code hab ich so umgesetzt:

PHP:
#select * from deltestMain;
$query = "select DBNr, DSId from tmp_sort WHERE DBNr = '$aktDB'";
$ergebnis = mysql_query($query) or die ("1. ".mysql_error());

#select * from deltestForeign;
$query2 = "select SpielerIDold from tmp_db26";
$ergebnis2 = mysql_query($query2) or die ("2. ".mysql_error());

$query3 = "create temporary table dontDel select distinct SpielerIDold from tmp_db26";
$ergebnis3 = mysql_query($query3) or die ("3. ".mysql_error());

$query4 = "delete from tmp_sort where DSId not in (select SpielerIDold from dontDel)";
$ergebnis4 = mysql_query($query4) or die ("4. ".mysql_error());
echo "g e s c h a f f t ?";

Da erscheint aber folgende Fehlermeldung:

4. You have an error in your SQL syntax. Check the manual that corresponds to your MySQL server version for the right syntax to use near 'select SpielerIDold from dontDel)' at line 1

Gruss von der Elbe zu der Elbe
 
Die ersten beiden Queries kannst Du Dir sparen, die habe ich nur gemacht, damit Du siehst, was in meinen Testtabellen steht.

Der Fehler kommt vermutlich daher, dass Du eine MySQL-Version vor 4.1 verwendest. Erst ab Version 4.1 beherscht MySQL Subqueries.

Eine Lösung für den von Dir geposteten Code wäre diese:
PHP:
$query3 = "select distinct SpielerIDold from tmp_db26";
$ergebnis3 = mysql_query($query3) or die ("3. ".mysql_error());

$arr=array();
while ($row=mysql_fetch_assoc($ergebnis3)) {
    $arr[]=$row['SpielerIDold'];
}

$inStr=implode(',',$arr);
$query4 = "delete from tmp_sort where DSId not in (".$inStr.")";
$ergebnis4 = mysql_query($query4) or die ("4. ".mysql_error());
echo "g e s c h a f f t ?";
Ob dass dann schnell genug geht, bleibt abzuwarten.

Dir fehlt jetzt gegenüber Deinem bisherigen Code auch noch eine Bedingung.
Statt dem Delete könntest Du dann auch Dein voriges Update machen:
PHP:
$query3 = "select distinct SpielerIDold from tmp_db26";
$ergebnis3 = mysql_query($query3) or die ("3. ".mysql_error());

$arr=array();
while ($row=mysql_fetch_assoc($ergebnis3)) {
    $arr[]=$row['SpielerIDold'];
}

$inStr=implode(',',$arr);

mysql_query("UPDATE tmp_sort SET Zusatz = 'n' WHERE DBNr = '$aktDB' AND DSId NOT IN (".$inStr.")");
Gruß hpvw
 
hi hpvw,
vielen Dank für deine Tips, jetzt funktioniert es (in ca. 10 min).

Ja ich hatte MySQL 4.x und jetzt bin ich auf 5.0.15 umgestiegen.

Wem es ineressiert:
Ich habe nun das XAMPP installiert und dies gibt es hier

http://www.apachefriends.org/de/

Nochmals vielen Dank an hpvw *zwinker

Gruss Heiko aus Sachsen-Anhalt
 
hi hpvw ich muss noch einmal stören :-)

meine DB hat jetzt das Problem das dr Index 1,2,3,507,509,2012,2013........ ist. Dies möchte ich einmalig hintereinander haben (es ist kein AUTOINDEX).

wenn ich, was man eigentlich wohl nicht soll, den Index ändern möchte, geht das auch wieder zu langsam. Und ich habe jetzt 2 Tage gebastelt (bin noch nicht Sattelfest mit Abfragen) aber ich komm zu keiner Lösung.

PHP:
$query = "select DBSort, IDold, IDnew from tmp_db24 WHERE DBSort = 'j' ";
$ergebnis = mysql_query($query) or die (mysql_error());
while ($row = mysql_fetch_array($ergebnis)) {
  $tmp_ID_old = $row['IDold'];  $tmp_ID_new = $row['IDnew'];
  mysql_query("UPDATE tmp_db26 SET SpielerIDnew = '$tmp_ID_new' WHERE SpielerIDold = '$tmp_ID_old' ");
  mysql_query("UPDATE tmp_db26 SET EwSpielerIDnew = '$tmp_ID_new' WHERE EwSpielerIDold = '$tmp_ID_old' ");
  mysql_query("UPDATE tmp_db26 SET AwSpielerIDnew = '$tmp_ID_new' WHERE AwSpielerIDold = '$tmp_ID_old' ");
}

Wie kann ich hier jetzt die Verbindung der 2 DB machen?

Danke und Gruss Heiko
 
Zurück