Forenindex » Programmierung/Entwicklung » PHP und MySQL » concat macht Probleme ab einer bestimmten Datenmenge

concat macht Probleme ab einer bestimmten Datenmenge

Polarpixel
Beiträge gesamt: 52

8. Aug 2003, 10:08
Bewertung:

gelesen: 2496

Beitrag als Lesezeichen
Hallo Leute,

ich habe mit Golive eine auf PHP und MySQL basierende Website aufgebaut. Die Datenbank habe ich nach und nach gefüllt.
Derzeit sind in der Haupttabelle ca. 440 Datensätze.

Ich habe nun festgestellt, dass seit kurzem eine Seite, auf der alle 440 Sätze ausgewählt werden (freilich nur immer mit 10 Stück pro Seite mit Weiter-/Zurückblättern), nicht mehr angezeigt wird, bzw. "befüllt" wird. Sie bleibt einfach weiß. Dies scheint ab einer bestimmten Datensatzzahl zu passieren; die Grenze lag bei mir bei ca. 400.

Ich kam dahinter, dass ein concat-Befehl im Select-Bereich dies verursacht, z.B.
select *, concat(nachname,', ',vorname) as gesamt from personen

Wenn ich dieses concat rausnehme und das Zusammensetzen des Namens via PHP mache, funktioniert alles.

Ist Euch bekannt, dass concat ab einer bestimmten Datenmenge Probleme verursacht? Mit 350 Datensätzen funktionerte dieser Weg nämlich noch - auch jetzt noch, wenn ich nur 2/3 der 440 Sätze selektiere.

Danke, beste Grüße,
Peter.

concat macht Probleme ab einer bestimmten Datenmenge

oesi50
  
Beiträge gesamt: 2315

8. Aug 2003, 10:45
Bewertung:

gelesen: 2496

Beitrag als Lesezeichen
hi Polarpixel

wie ist denn bei Dir das Weiterblättern realisiert? Normalerweise geht ja so was mit LIMIT in der SELECT Anweisung.

Versuche zusätzlich noch auf "SELECT * ..." zu verzichten und statt dessen alle benötigten Felder direkt anzugeben.

am MYSQL liegt dein Problem bestimmt nicht, ich habe hier eine Datenbank mit ca.:35000 DS.

Mit dieser Anweisung

SELECT message,concat(provider,';',link) AS hlink FROM newsticker LIMIT 10000, 10

gebe ich zum Beispiel 10 Nachrichten ab der Datensatznummer 10000 aus.

Grüße Oesi

PS.: Teste doch mal Deine SQL-Anweisungen mit PHPMYADMIN.



(Dieser Beitrag wurde von oesi50 am 8. Aug 2003, 10:49 geändert)

concat macht Probleme ab einer bestimmten Datenmenge

Polarpixel
Beiträge gesamt: 52

8. Aug 2003, 11:35
Bewertung:

gelesen: 2496

Beitrag als Lesezeichen
Hallo Oesi,

mit phpMyAdmin war es genauso.
Ich hatte nicht erwähnt (um es nicht zu kompliziert zu machen), dass ich drei Tabellen per IDs in der Select-Abfrage verknüpft habe. Eine Tabelle hat 440 Sätze, eine 273, eine 9.
In dieser Kombination (Verknüpfung, concat, alle Datensätze) geht es nicht.
Lasse ich entweder die Verknüpfung der drei Tabellen oder concat weg, funktioniert es.

Nun habe ich aber mal Deinen Tipp probiert, im Select statt * alle Felder konkret zu nennen, was eine Menge Tipparbeit ist, da ich in allen drei Tabelle insgesamt ca. 40 Felder habe und auch alle brauche.
Und siehe da - es klappt nun!! Aber warum? Ich dachte, das sei egal, ob man * schreibt oder alle Felder nennt?

Vielen Dank!

Peter.

concat macht Probleme ab einer bestimmten Datenmenge

oesi50
  
Beiträge gesamt: 2315

8. Aug 2003, 12:08
Bewertung:

gelesen: 2496

Beitrag als Lesezeichen
das ist ja genau das Problem wenn mehrere Tabellen verknüpft werden.

hier muss mindestens so was stehen:

SELECT tab1.*,tab2.*,tab3.* ...

aber auch das ist nicht so gut.

Die beste Lösung ist immer noch(auch bei anderen DB-Systemen), die Felder IMMER explizit anzugeben und auf den * ganz zu verzichten. Für die Performance ist es auch wichtig, nur die wirklich benötigten Felder abzufordern. Warum soll ich Daten abfragen, die ich nicht benötige. Damit wird
erstens die DB unnötig in Anspruch genommen,
zweitens wird Traffic in Anspruch genummen, und
drittens muss ich mich dann auch noch bei der Weiterverarbeitung um die zu ignorierenden Daten kümmern(Arrays belegen zusätzlichen Speicherplatz, zusätzliche Indizierungen sind notwendig, u.U. ist auch zusätzliche Programmlogik notwendig, und, und, und).

Der kleine Stern wirkt sich also mindestens aus auf:

- CPU Auslastung
- Speicherplatzverbrauch
- Programmgröße
- Datentransfer
- Programmlaufzeit
- Wartbarkeit des Programmes
- Programmierzeit
- Fehlersuchzeit

Das sollten erst mal die wichtigsten Punkte sein.
Bitte niemals den * in irgend einer SELECT Anweisung verwenden!
Die einzige Ausnahme ist zum TESTEN mit irgendwelchen SQL-Tools.
Gerade bei einer Verknüpfung benötigt man NIE alle Felder.
Wer braucht schon 'tab1.id,tab2.id,tab3.id' wenn er z.B. einen EQUI JOIN über die ID macht?
Bei deinem Beispiel ist ja bestimmt noch name und vorname überflüssig, da nur das mit concat neu erzeugte Datenfeld benötigt wird.

Grüße Oesi

(Dieser Beitrag wurde von oesi50 am 8. Aug 2003, 12:24 geändert)

concat macht Probleme ab einer bestimmten Datenmenge

Polarpixel
Beiträge gesamt: 52

8. Aug 2003, 12:54
Bewertung:

gelesen: 2496

Beitrag als Lesezeichen
Hallo Oesi,

Ich danke Dir herzlich für Deine Tipps und Deine Hilfe und ausführlichen Erläuterungen,
Peter.

concat macht Probleme ab einer bestimmten Datenmenge

Miro Dietiker
Beiträge gesamt: 699

8. Aug 2003, 13:01
Bewertung:

gelesen: 2496

Beitrag als Lesezeichen
Hi there!

Es gibt manche Fälle wo ich die Tabelle gerne mit "tab.*" auslese
und das auch in Anwendungen welche nicht nur Testapplikationen sind.

Bedenke, dass mysql die eingegebene Spaltenbezeichnungen noch parsen
muss, prüfen ob denn diese Spalten auch wirklich alle existieren,
die internen Spalten(-und reihenfolgen) in die eingegebene
Reihenfolge umstellen, usw..

Ich wage zu behaupten dass ein "tab.*" um einiges effizienter ist
für das Auslesen von Spalten, als die explizite Angabe von allen
Spalten - wenn man denn alle braucht. Ein reiner * jedoch sehe ich
auch sehr ungern. Man muss sich auch immer bewusstsein, dass bei
verbundenen Tabellen Namenskollisionen entstehen!

Lehnst du diese Art von Argumentation für den Einsatz von "tab.*"
so auch kategorisch ab?

GrEeZ: Miro Dietiker

concat macht Probleme ab einer bestimmten Datenmenge

Anonym
Beiträge gesamt: 22827

8. Aug 2003, 13:39
Bewertung:

gelesen: 2496

Beitrag als Lesezeichen
hi Miro,

der Ablauf(stark vereinfacht):

1. *
- SELECT (deutlich kürzer)
- DB durchsucht die Tabellendefinitionen nach den Feldern und erzeugt eine Feldliste
- Parser parst
- Ergebis wird geliefert

2. Feldnamen

- SELECT (oft deutlich länger)
- DB prüft in der Tabellendefinitionen die Gültigkeit der Feldnamen
- Parser parst
- Ergebis wird geliefert

Die Frage ist: was ist schneller
- Query mit allen Felddefinitionen ergänzen
- Feldnamen prüfen

Bei verketteten Tabellen wird das natürlich noch schwieriger, weil ja oft Namenskollisionen auftreten, die irgendwie vom DB-System gehandelt werden müssen.

Das entsprechende Benchmarking ist ja leicht auszuführen.

Der wichtigste Punkt ist aber die Programmwartbarkeit.

Was passiert zum Beispiel, wenn ein anderer Entwickler noch Datenfelder hinzufügt oder entfernt oder die Positionen tauscht. An welcher Stelle tritt der Fehler auf. Mit * irgendwo im Programm, mit Feldnamen sofort bei der entsprechenden Query.

Was passiert, wenn ich Datenfelder hinzufüge, die evtl. in einem anderen Modul benötigt werden. Mit Feldnamen kein Problem, alle Namen sind genau definiert und werden genau so verarbeitet wie geplant.

Mit * geht der Zirkus los, alle Module dursuchen, Queries anpassen, Indizes ändern usw.(Man vergisst natürlich immer was und merkt's erst ein halbes Jahr später).

Im Sinne der Programmwartbarkeit ist es natürlich auch besser, wenn schon in der Query, die Feldnamen lesbar erscheinen, das hilft nach ein paar Monaten ungemein. Selbstverständlich sollte auch die Anweisung strukturiert niedergeschrieben werden.

Bsp:
SELECT
t1.id, t1,name,
t2.ort, t2.plz,
t3.abteilung, t3.gehalt,
AVG(t3.blabla)
FROM t1
JOIN t2
ON blabla
JOIN t3
ON blabla
WHERE blabla
GROUP BY blabla
ORDER BY blabla

wenn ich solche Abfragen im Programmcode habe, spare ich eine Menge Sucherei.

Verarbeitung der Resultate:

Es ist deutlich schneller, wenn die Resultate ausschließlich in einem indizierten Array geliefert werden, da ja mit der Query bereits die Reihenfolge definiert wurde. Das klappt nur ohne Stern.

Mit Stern ist man oft auf Hash Arrays angewiesen, was im allgemeinen mehr CPU benötigt als ein reines Indexarray.
Mit * bzw tab.* besteht außerdem immer die Möglichkeit, dass zu viele Datenfelder übertragen werden, besonders beim JOIN.

Am schlimmsten finde ich die Variante, beide Versionen gleichzeitig zu erstellen.

Tip:
Nimm Dir doch mal ein Benchmarking Tool und teste die div. Varianten durch. Du wirst Dich wundern, was da zu Tage kommt.

Grüße Oesi

concat macht Probleme ab einer bestimmten Datenmenge

oesi50
  
Beiträge gesamt: 2315

8. Aug 2003, 13:42
Bewertung:

gelesen: 2496

Beitrag als Lesezeichen
ups, rausgeflogen

Das Forum hat mir meine Leerzeichen geklaut. Die Anweisung ist natürlich noch sinngemäß eingerückt.

Grüße Oesi

concat macht Probleme ab einer bestimmten Datenmenge

Polarpixel
Beiträge gesamt: 52

8. Aug 2003, 13:48
Bewertung:

gelesen: 2496

Beitrag als Lesezeichen
Hallo, Ihr beiden,

nun muss ich als Neuling hier doch noch ne Frage loswerden:
Würdet Ihr die Verknüpfung von drei Tabellen über where oder über join vornehmen?

Ich fand die where-Variante irgendwie leichter:
select a, b, c, d from x, y, z where a.x = b.y and c.y = d.z

Gibt es Gründe, die für eine Join-Lösung sprechen (wobei ich im Moment gar nicht wüsste, wie das mit drei Tabellen geht...)

Danke,
Peter.

concat macht Probleme ab einer bestimmten Datenmenge

oesi50
  
Beiträge gesamt: 2315

8. Aug 2003, 13:52
Bewertung:

gelesen: 2496

Beitrag als Lesezeichen
Noch ein Orinaltext aus der MYSQL Doku zum Thema

Optimizing the application

* One should concentrate on solving the problem.
* When writing the application one should decide what is most important:
o Speed
o Portability between OS
o Portability between SQL servers
* Use persistent connections.
* Cache things in your application to lessen the load of the SQL server.
* Don't query columns that you don't need in your application.
* Don't use SELECT * FROM table_name...
* Benchmark all parts of your application, but put the most effort into benchmarking the whole application under the worst possible 'reasonable' load. By doing this in a modular fashion you should be able to replace the found bottleneck with a fast 'dummy module', you can then easily identify the next bottleneck (and so on).
* Use LOCK TABLES if you do a lot of changes in a batch; For example group multiple UPDATES or DELETES together.


Der gesamt Text ist hier zu lesen

http://www.mysql.com/...-20000719/index.html

Grüße Oesi

concat macht Probleme ab einer bestimmten Datenmenge

oesi50
  
Beiträge gesamt: 2315

8. Aug 2003, 14:06
Bewertung:

gelesen: 2496

Beitrag als Lesezeichen
@Polarpixel

Deine Frage ist nicht so leicht zu beantworten.

Im allgemeinen ist es besser JOIN zu verwenden. Gegebenenfalls kann man auch mit der Reihenfolge der JOINs experimentieren, das bringt besonders bei großen Tabellen oft trastische Geschwindigkeitsunterschiede.
Leider ist das abhängig vom verwendeten Datenbankdesign(Normalisierungsgrad, Komplexität der Beziehungen, erwartetes Ergebnis,...)

Als Faustregel gilt aber, lieber JOIN als WHERE bzw. JOIN und WHERE SINNVOLL gemischt.
Bei alleiniger Verwendung von WHERE, erzeugt die Datenbank im schlimmsten Fall intern erstmal das kartesische Produkt und wendet erst dann deine WHERE Clausel an.

Bei deinem Beispiel sind das ca. 1.188.000(!) Datensätze, die irgendwo temporär im Datenbankserver erzeugt werden.

Umsetzung WHERE -> JOIN

Deine Anweisung
select a, b, c, d from x, y, z where a.x = b.y and c.y = d.z
(Deine Feldbezeichnungen sind vertauscht)

sieht dann so aus:

SELECT a, b, c, d
FROM x
JOIN z
ON x.a = y.b
JOIN z
ON y.c = z.d
WHERE nochirgendwas
ORDER BY nochwasanderes

praktisches Beispiel:
$sql="
SELECT aufgabe,datum_a,name_a,id,u_email,projekt
FROM $t_daten
LEFT JOIN $t_user
ON name_a = u_name
LEFT JOIN $t_pro
ON $t_daten.p_id = $t_pro.p_id
WHERE (datum_e = '' OR name_e = '')
ORDER BY projekt ASC,datum_a DESC
";

Grüße Oesi

(Dieser Beitrag wurde von oesi50 am 8. Aug 2003, 15:22 geändert)

concat macht Probleme ab einer bestimmten Datenmenge

oesi50
  
Beiträge gesamt: 2315

8. Aug 2003, 14:39
Bewertung:

gelesen: 2496

Beitrag als Lesezeichen
Hier ist noch was zum lesen:

http://www.php-center.de/...mysql/mysql-127.html

Grüße Oesi