![]() |
Datenbank: firebird • Version: 2.1 • Zugriff über: zeos
Geschwindigkeit diverser SQL-Statments
hallo zusammen,
man liest ja immer wieder mal, dass sql-statments ala "select * from..." vermieden werden sollen. Gibt es einen erkennbaren bzw. messbaren Unterschied in der Zugriffsgeschwindigkeit zwischen einem statement das alle Datenfelder holt, oder einem welches nur 2 felder abfragt? also beipielsweise zwischen "select * from kunden" oder *select id, name from kunden" wobei die Kundentabelle ,sagen wir mal insgesamt 20 felder hat. Danke Gruss KH |
Re: Geschwindigkeit diverser SQL-Statments
Es kommt natürlich auch darauf an, was für Felder es sind. Bei 20 großen Varchar-Feldern wirst du es mehr merken als bei Numeric.
Noch wichtiger ist es aber die Anzahl der zurückgegebenen Datensätze zu beschränken. |
Re: Geschwindigkeit diverser SQL-Statments
Bei einem langsamen Netzwerk und nicht benötigten BLOB-Feldern dürfte der Unterschied auch subjektiv zu spüren sein, denke ich mal.
|
Re: Geschwindigkeit diverser SQL-Statments
Zitat:
|
Re: Geschwindigkeit diverser SQL-Statments
LIMIT x, y; TOP x; ...
|
Re: Geschwindigkeit diverser SQL-Statments
Code:
Firebird:
Firebird: FIRST
Firebird >= 2: ROWS n TO m MySQL: LIMIT MSSQL: TOP Oracle: ROWNUM PostgreSQL: LIMIT + OFFSET ![]() |
Re: Geschwindigkeit diverser SQL-Statments
... und natürlich immer mit einer sinnvollen WHERE-Klausel. Jürgen
|
Re: Geschwindigkeit diverser SQL-Statments
Zitat:
|
Re: Geschwindigkeit diverser SQL-Statments
Hi
Zitat:
die zurückgegebene Datenmenge bezüglich Spalten und Zeilen nur so groß wie nötig und so klein wie möglich halten. |
Re: Geschwindigkeit diverser SQL-Statments
Moin,
was auch noch einen grossen Unterschied macht ist die Reihenfolge der WHERE-Bedingungen und/oder JOINs. Der Query-Optimizer kommt da nicht immer ganz gut mit (hab ich z.B. bei MySQL gemerkt). Nehmen wir dieses Query:
SQL-Code:
Das ist nicht dasselbe wie das hier:
SELECT * FROM a, b WHERE a.id = b.id AND a.user = 5
SQL-Code:
Der Unterschied liegt darin, dass beim ersten Query zuerst ein Kreuzprodukt erstellt wird. Vor allem in m:n-Beziehungen koennen da viele Datensaetze zusammenkommen. Anschliessend wird die Datenmenge eingeschraenkt. Beim zweiten Query wird zuerst eingeschraenkt und anschliessend erst das Kreuzprodukt erstellt, das heisst die aufkommende Datenmenge wird kleiner sein. Wenn nun auch b eine user-ID haette (die natuerlich dieselbe ist wie bei a, kann ja sein) dann koennte man auch das noch machen:
SELECT * FROM a, b WHERE a.user = 5 AND a.id = b.id
SQL-Code:
So werden in beiden Tabellen erstmal die Datensaetze eingeschraenkt, bevor das Kreuzprodukt daherkommt.
SELECT * FROM a, b WHERE a.user = 5 AND b.user = 5 AND a.id = b.id
Was den * betrifft: Wenn du alle Felder brauchst, dann schreib auch den * rein. Der Query-Optimizer muss eh jedes Feld durch seinen vollen Namen ersetzen (<datenbank>.<tabelle>.<feld>), da macht das mitm * auch keinen Unterschied. Die meisten Server vertragen den * mittlerweile auch sehr gut. V.a. bei Count-Statements (SELECT COUNT(*) FROM xyz) gehts mitm * immer noch am schnellsten. Was teilweise einen grossen Unterschied macht ist die Verwendung von DISTINCT oder GROUP BY. Da kann man teilweise auch einiges rausholen. Im Grunde genommen kann man keine allgemeingueltigen Regeln aufstellen. Manchmal muss man einfach damit leben, dass ein Query langsam laeuft (z.B. wenn ich Daten aus drei Tabellen hole, in denen jeweils mehr als 1 Million Datensaetze drin sind). Die Optimierung geschieht dabei meistens auf Query-Basis, d.h. guck dir das Query mit EXPLAIN an, versuch rauszufinden was du dran aendern kannst, usw. Teilweise reicht es ja auch, das Schema geringfuegig zu aendern. Um kurz ein Beispiel zu nennen: Wir haben eine Seite in der Artikel stehn. Diese Artikel stehen in verschiedenen Kategorien. Auf der Uebersichtsseite will ich natuerlich die Kategorien zusammen mit Infos zum letzten Artikel anzeigen. Wie wuerde man das machen, wenns streng nach Protokoll geht (MySQL):
SQL-Code:
Und zum Rausholen der Artikel in der Anzeigeschleife:
SELECT * FROM categories ORDER BY category_order
SQL-Code:
Das ist schon nicht schlecht. Wenn ich nun aber die ID des letzten Beitrags der Kategorie im Datensatz der Kategorie hinterlege, hab ich zwar eine Redundanz in der DB und Normalform-Fetischisten wuerden gleich wieder Zeter und Mordio bruellen, aber dafuer geht sowas:
SELECT * FROM articles WHERE category_id = <id> ORDER BY article_time DESC LIMIT 1
SQL-Code:
Und schon wars das. Dann noch ein Index auf c.last_article und c.category_order, a.id als Primary und der Datenbankserver wird dir zum Dank ein Kuesschen mit jedem Query-Ergebnis mitschicken *g* ;)
SELECT c.*, a.id, a.time FROM categories c LEFT JOIN articles a ON c.last_article = a.id ORDER BY category_order
Mein Tipp: teste verschiedene Varianten eines Queries rum und guck dir an, was der Optimizer daraus macht. In MySQL kannst du das sehn in dem du zuerst das Query mit EXPLAIN ausfuehrst:
SQL-Code:
und dir anschliessend die Warnungen anzeigen laesst:
EXPLAIN EXTENDED SELECT .....
SQL-Code:
Dann zeigt dir MySQL das Query an, wie es dann tatsaechlich ausgefuehrt wurde. Da kann man auch schon Engpaesse sehn. In den meisten Faellen reicht es jedoch, folgendes zu machen:
SHOW WARNINGS;
SQL-Code:
Das gibt dir Informationen ueber das Query und die Abarbeitungsreihenfolge. Da lassen sich die Engpaesse mit etwas Erfahrung auch gut sehen :)
EXPLAIN SELECT .....
Greetz alcaeus |
Re: Geschwindigkeit diverser SQL-Statments
Das MySQL noch nicht einmal einfachste Optimierungen hinbekommt (hier über generische Indexstatistiken, ein 10-Zeiler), ist ein weiteres Argument für andere RDBMS, z.B. Firebird (die offenbar bevorzugte DB des Threadstartes).
Konstrukte, die Tabellen verknüpfen und so aussehen, sind zu vermeiden:
SQL-Code:
.
select * from a,b where a.id = b.id
Besser ist die Verwendung eines JOINS
SQL-Code:
Neben den üblichen Fallstricken, über die man bei komplexeren Queries stolpert, wenn man die bequeme Komma-Schreibweise benutzt, ist es auch organisatorisch sinnvoller, zwischen Verknüpfungs- und Filterbedingungen zu trennen.
select * from a join b on a.id = b.id
Anstatt also:
SQL-Code:
zu schreiben, wäre hier ein
select * from a,b,c where a.id = b.id and a.user = 5 and a.xid = c.xid
SQL-Code:
besser.
select *
from a join b on a.id = b.id join c on a.xis = c.xid where a.user = 5 Speziell bei sehr komplexen Queries verliert man sonst den Überblick. Ein Query-Optimizer kann eine Where-Klausel, die wirklich nur filtert, auch wesentlich besser optimieren, da die Verknüpfungsbedingungen bereits in den JOINs verwurstet sind (und i.a. eh auf PKs aufsetzen). Man sollte auch nicht vergessen, das der Optimizer durch alle Kombinationen der Where-Klausel durchprobiert (einige machen das zumindest). @alcaeus: Wenn ihr ein besseresanderes RDBMS genommen hättet, würdet ihr nicht so viel Zeit mit Query-Optimierungen verbraten. :mrgreen: Andere DBs machen eure Handoptimierungen automatisch. MSSQL z.B. ignoriert ein ORDER BY (bzw. verbrät 0.0 ms Zeit), wenn die Sortierspalten über einen 'Clustered Index' indexiert sind, denn dann stimmt die Reihenfolge der Datensätze schon. Also kann man getrost sortieren und nur den obersten Datensatz nehmen. Dessenungeachtet ist deine/eure Lösung aber eh besser, weil es eine Anforderung ('zeig mir den letzten...') integral im DB-Design verankert und nicht versucht, über RDBMS-spezifische Features hier ein schnelles Ergebnis zu bekommen: Euer DB-Design wird auch auf einem anderen RDBMS performant ablaufen. |
Re: Geschwindigkeit diverser SQL-Statments
ich danke euch für eure Meinungen und Beiträge.
Gruss KH |
Alle Zeitangaben in WEZ +1. Es ist jetzt 11:57 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz