![]() |
Wie MySQL-Abfrage optimieren? (große Tabelle, Dauer: 0.2s)
Hallo,
ich habe 2 MySQL-Tabellen, die wie folgt aufgebaut sind:
SQL-Code:
CREATE TABLE `log_parser_ips` (
`ip_from` INTEGER(10) UNSIGNED NOT NULL DEFAULT '0', `ip_to` INTEGER(10) UNSIGNED NOT NULL DEFAULT '0', `cc` CHAR(2) COLLATE utf8_unicode_ci NOT NULL DEFAULT '', PRIMARY KEY (`ip_from`), UNIQUE KEY `ip_to` (`ip_to`), UNIQUE KEY `ip_from` (`ip_from`), KEY `cc` (`cc`) )ENGINE=MyISAM ROW_FORMAT=FIXED CHARACTER SET 'utf8' COLLATE 'utf8_unicode_ci';
SQL-Code:
Die Tabelle "log_parser_ips" enthält die IP-Adressenbereiche (ip_from / ip_to) und ordnet diese einem Ländercode (cc) zu.
CREATE TABLE `log_parser_countries` (
`cc` CHAR(2) COLLATE utf8_unicode_ci NOT NULL DEFAULT '', `country` VARCHAR(64) COLLATE utf8_unicode_ci NOT NULL DEFAULT '', PRIMARY KEY (`cc`) )ENGINE=MyISAM CHARACTER SET 'utf8' COLLATE 'utf8_unicode_ci'; Die Tabelle ""log_parser_countries" ordnet den Ländercodes (cc) den Ländernamen (country) zu. Anhand der IP ermittel ich das Land folgendermaßen:
SQL-Code:
Wenn ich die Abfrage ohne "JOIN" ausführe:
SELECT c.country, c.cc FROM log_parser_countries c
JOIN log_parser_ips i ON i.cc = c.cc WHERE i.ip_from <= 123456789 AND i.ip_to >= 123456789 LIMIT 1
SQL-Code:
ändert sich nichts, was die Ausführungszeit betrifft. Diese liegt durchschnittlich bei stolzen 0.2 Sekunden.
SELECT c.country, c.cc FROM log_parser_countries c, log_parser_ips i
WHERE i.ip_from <= 123456789 AND i.ip_to >= 123456789 AND i.cc = c.cc LIMIT 1 Wie kann ich das optimieren? Ich habe schon überlegt, anstelle der Spalte "cc" (CHAR) für die Zuordnung eine Integer-Spalte zu verwenden. Aber ob das so viel bringt, weiß ich nicht. Grüße, Matze |
Re: Wie MySQL-Abfrage optimieren? (große Tabelle, Dauer: 0.2
Zitat:
2, Verwendung von Stored Procedures |
Re: Wie MySQL-Abfrage optimieren? (große Tabelle, Dauer: 0.2
Hallo Bernhard,
danke für deine Antwort. Ich habe mich mal in die Prepared Statements eingearbeitet, doch ändert sich die Ausführungszeit leider nicht. Mein PHP-Code schaut so aus:
Code:
Grüße, Matze
$this->[color=#018801]db_connection[/color] = [b][color=#0000ff]new[/color][/b] [color=#018801]mysqli[/color]($conf_db[[color=#df0000]'host'[/color]], $conf_db[[color=#df0000]'user'[/color]], $conf_db[[color=#df0000]'passwd'[/color]], $conf_db[[color=#df0000]'name'[/color]]);
[b][color=#0000ff]if[/color][/b] ([color=#018801]mysqli_connect_errno[/color]()) [b][color=#0000ff]die[/color][/b]([color=#018801]mysqli_connect_error[/color]() . [color=#df0000]' - '[/color] . [color=#018801]mysqli_connect_errno[/color]()); $this->[color=#018801]db_statement[/color] = $this->[color=#018801]db_connection[/color]->[color=#018801]prepare[/color]([color=#df0000]"SELECT c.country, c.cc FROM log_parser_countries c JOIN log_parser_ips i ON i.cc = c.cc WHERE i.ip_from <= ? AND i.ip_to >= ? LIMIT 1"[/color]); [b][color=#0000ff]if[/color][/b] (!$this->[color=#018801]db_statement[/color]) [b][color=#0000ff]echo[/color][/b] $this->[color=#018801]db_connection[/color]->[color=#018801]error[/color]; $this->[color=#018801]db_statement[/color]->[color=#018801]bind_param[/color]([color=#df0000]"ii"[/color], $ip, $ip); [b][color=#0000ff]if[/color][/b] (!$this->[color=#018801]db_statement[/color]->[color=#018801]execute[/color]()) [b][color=#0000ff]echo[/color][/b] $this->[color=#018801]db_statement[/color]->[color=#018801]error[/color]; $this->[color=#018801]db_statement[/color]->[color=#018801]bind_result[/color]($country, $cc); [b][color=#0000ff]if[/color][/b] (!$this->[color=#018801]db_statement[/color]->[color=#018801]fetch[/color]()) [b][color=#0000ff]echo[/color][/b] [color=#df0000]'empty mysql result'[/color]; $this->[color=#018801]db_connection[/color]->[color=#018801]close[/color](); PS: Falls sich das nun zu einer PHP-Frage entwickelt, verschiebe ich das Thema. |
Re: Wie MySQL-Abfrage optimieren? (große Tabelle, Dauer: 0.2
Zitat:
|
Re: Wie MySQL-Abfrage optimieren? (große Tabelle, Dauer: 0.2
Hast Du mal ein Explain-Select darauf losgelassen? Damit könntest Du weitere Indizien auf den Flaschenhals bekommen.
(Einfach das Keyword "EXPLAIN" vor das Statement schreiben und dann in phpMyAdmin oder wo auch immer ausführen.) |
Re: Wie MySQL-Abfrage optimieren? (große Tabelle, Dauer: 0.2
Ich schließe mich DeddyH an. Ein kombinierter Index würde wohl besser funktionieren
|
Re: Wie MySQL-Abfrage optimieren? (große Tabelle, Dauer: 0.2
Hi,
@Deddy: Hm ich bin mir nicht so ganz sicher, aber da die Zahlen nicht doppelt vorkommen, habe ich UNIQUE gesetzt. @Daniel: EXPLAIN kannte ich bisher gar nicht. Interessantes Feature, doch mit dem Ergebnis fange ich leider nichts an, was mich bzgl. Performance weiterbringen könnte:
Code:
@mquadrat: Meinst du sowas "PRIMARY KEY (`ip_to`, `ip_from`)"?
id select_txpe table type possible_keys key ken_len ref rows Extra
---------------------------------------------------------------------------------------------------------------- 1 SIMPLE i range PRIMARY,ip_to,ip_from,cc PRIMARY 4 NULL 27 Using where 1 SIMPLE c eq_ref PRIMARY PRIMARY 6 db.i.cc 1 Falls ja, auch da merke ich keinen Unterschied. Grüße, Matze |
Re: Wie MySQL-Abfrage optimieren? (große Tabelle, Dauer: 0.2
Das Explain verrät dir in diesem Beispiel, dass er für die Bereichsprüfung die Indizes PRIMARY, ip_to, ip_from und cc einsetzen könnte, sich aber für den PRIMARY entscheidet. Dabei findet er 27 Einträge, die dann mit einem where auf einen reduziert werden.
|
Re: Wie MySQL-Abfrage optimieren? (große Tabelle, Dauer: 0.2
Hi mquadrat,
ok, aber was sagt mir das nun genau? Dass die anderen Indizes überflüssig sind? Oder kann ich irgendwas herauslesen, damit ich die Abfrage beschleunigen kann? Grüße, Matze |
Re: Wie MySQL-Abfrage optimieren? (große Tabelle, Dauer: 0.2
Wenn das die einzige Query auf die Tabelle ist, dann kannst du die anderen Indizes tatsächlich entfernen. Hat aber eher Einfluß auf die Schreib-Performance. Mittels Explain kann man seine Indizes "tunen". Je weniger Datensätze durch den Index durchkommen, desto besser. Bei nem kombinierten müsste da eigentlich statt der 27 eine 1 stehen..
Hast du davon irgendwo einen Dump, damit man das mal ausprobieren kann? |
Re: Wie MySQL-Abfrage optimieren? (große Tabelle, Dauer: 0.2
Zitat:
Code:
Aber wieso das so ist. :gruebel:
id select_txpe table type possible_keys key ken_len ref rows Extra
---------------------------------------------------------------------------------------------------------------- 1 SIMPLE i ALL PRIMARY NULL NULL NULL 234 1 SIMPLE c ref PRIMARY,cc cc 6 db.c.cc 385 Using where Einen Dump habe ich leider keinen da. Und das zu exportieren wäre etwas groß (vielleicht 4-5 MB). |
Re: Wie MySQL-Abfrage optimieren? (große Tabelle, Dauer: 0.2
Was haste denn geändert zwischen den zwei Explains? Jetzt benutzt er gar keinen Index mehr ;)
|
Re: Wie MySQL-Abfrage optimieren? (große Tabelle, Dauer: 0.2
Die "log_parser_ips"-Tabelle sieht nun so aus:
SQL-Code:
Grüße
CREATE TABLE `log_parser_ips` (
`ip_from` INTEGER(10) UNSIGNED NOT NULL DEFAULT '0', `ip_to` INTEGER(10) UNSIGNED NOT NULL DEFAULT '0', `cc` CHAR(2) COLLATE utf8_unicode_ci NOT NULL DEFAULT '', PRIMARY KEY (`ip_to`, `ip_from`), KEY `cc` (`cc`) )ENGINE=MyISAM ROW_FORMAT=FIXED CHARACTER SET 'utf8' COLLATE 'utf8_unicode_ci'; |
Re: Wie MySQL-Abfrage optimieren? (große Tabelle, Dauer: 0.2
mhh dann arbeitet der mySQL Optimierer wohl anders, als ich dachte :D
Ich würde jetzt auch einfach nur noch hin- und herprobieren (geht ohne Daten halt schlecht). |
Re: Wie MySQL-Abfrage optimieren? (große Tabelle, Dauer: 0.2
Liste der Anhänge anzeigen (Anzahl: 1)
Gezippt ist das alles schnuckelig klein, merke ich gerade. ;)
Wenn du herumtesten möchtest, gerne. :-) |
Re: Wie MySQL-Abfrage optimieren? (große Tabelle, Dauer: 0.2
Probier einen Index auf ip_from (eventuell auch auf ip_to) zu setzten:
Code:
KEY `ip_from` (`ip_from`)
|
Re: Wie MySQL-Abfrage optimieren? (große Tabelle, Dauer: 0.2
Habe zwar auch keine Lösung aber ne Menge links hierzu (gegoogelt) gefunden:
![]() kann man als MySQL Dump downloaden ![]() download SQL-Format (zip,460kB) ![]() ![]() Für SQL Abfragen ![]() Offizielle Seite: ![]() denke der sollte helfen. Falls überflüssig einfach den Beitrag löschen. |
Re: Wie MySQL-Abfrage optimieren? (große Tabelle, Dauer: 0.2
:D
Das Ding arbeitet wie Firebird. Die Spaltenreihenfolge muss in Query und Index gleich sein.
SQL-Code:
mit Index auf ip_from, ip_to
Zeige Datensätze 0 - 0 (1 insgesamt, die Abfrage dauerte 0.0004 sek.)
SQL-Befehl: SELECT c.country, c.cc FROM log_parser_countries c JOIN log_parser_ips i ON i.cc = c.cc WHERE i.ip_from <=123456789 AND i.ip_to >=123456789 LIMIT 1 |
Re: Wie MySQL-Abfrage optimieren? (große Tabelle, Dauer: 0.2
Hallo
@user0815: Danke, doch eine Liste habe ich ja bereits und einen MySQL-Client auch. ;) @mquadrat: Hm das klingt gut, aber irgendwie bekomme ich es nicht hin. Meine Tabellen sehen nun so aus:
SQL-Code:
Hast du diese auch so oder anders?
CREATE TABLE `log_parser_ips` (
`ip_from` INTEGER(10) UNSIGNED NOT NULL DEFAULT '0', `ip_to` INTEGER(10) UNSIGNED NOT NULL DEFAULT '0', `cc` CHAR(2) COLLATE utf8_unicode_ci NOT NULL DEFAULT '', KEY `ips` (`ip_from`, `ip_to`) )ENGINE=MyISAM ROW_FORMAT=FIXED CHARACTER SET 'utf8' COLLATE 'utf8_unicode_ci'; CREATE TABLE `log_parser_countries` ( `cc` CHAR(2) COLLATE utf8_unicode_ci NOT NULL DEFAULT '', `country` VARCHAR(64) COLLATE utf8_unicode_ci NOT NULL DEFAULT '', PRIMARY KEY (`cc`) )ENGINE=MyISAM CHARACTER SET 'utf8' COLLATE 'utf8_unicode_ci'; Grüße, Matze |
Re: Wie MySQL-Abfrage optimieren? (große Tabelle, Dauer: 0.2
Deiner #1
SQL-Code:
Meiner, habe andere Tabellen genommen sowie Felder umbenannt.
SELECT c.country, c.cc FROM log_parser_countries c
JOIN log_parser_ips i ON i.cc = c.cc WHERE i.ip_from <= 123456789 AND i.ip_to >= 123456789 LIMIT 1
SQL-Code:
Also eigentlich kein Unterschied. Das Feld ISO2 ist in beiden Tabellen vom Typ varchar(2) und es liegt jeweils ein INDEX auf dem Feld ISO2.
SELECT c.Continent, c.IntName, c.Name FROM countrys_de c
JOIN t_ipbereich i ON i.ISO2 = c.ISO2 WHERE i.ipfrom <= 123456789 AND i.ipto >= 123456789; Mit dem MySQL Query Browser braucht die Abfrage: 0,0009 s (0,0003) geholt Mit phpMyAdmin: Zeige Datensätze 0 - 0 (1 insgesamt, die Abfrage dauerte 0.0005 sek.) countrys_de = 249 Einträge t_ipbereich = 58143 Einträge |
Re: Wie MySQL-Abfrage optimieren? (große Tabelle, Dauer: 0.2
@Matze
Ich hab dein .Sql File genommen und eingelesen. Danach hab ich nur den Index geändert.
SQL-Code:
--
-- Tabellenstruktur für Tabelle `log_parser_countries` -- CREATE TABLE IF NOT EXISTS `log_parser_countries` ( `cc` char(2) collate utf8_unicode_ci NOT NULL default '', `country` varchar(64) collate utf8_unicode_ci NOT NULL default '', PRIMARY KEY (`cc`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; -- -------------------------------------------------------- -- -- Tabellenstruktur für Tabelle `log_parser_ips` -- CREATE TABLE IF NOT EXISTS `log_parser_ips` ( `ip_from` int(10) unsigned NOT NULL default '0', `ip_to` int(10) unsigned NOT NULL default '0', `cc` char(2) collate utf8_unicode_ci NOT NULL default '', PRIMARY KEY (`ip_from`,`ip_to`), KEY `cc` (`cc`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci ROW_FORMAT=FIXED; |
Re: Wie MySQL-Abfrage optimieren? (große Tabelle, Dauer: 0.2
Hm komisch, so hatte ich es eigentlich auch.
PHP zeigt mir auch dann knapp 0.2 Sekunden an, seltsam. MySQLQueryBrowser nur 0.0046 Sekunden. Dann dürfte letzteres wohl stimmen. :-) Ich danke euch. Grüße, Matze |
Re: Wie MySQL-Abfrage optimieren? (große Tabelle, Dauer: 0.2
Neulich kam ein ehamaliger Mitarbeiter mit einem Db-Problem zu mir: Windows, PHP und MySQL. War grottenlangsam. Ob ich mir seine DB-Struktur mal anschauen kann: Soweit alles super, 3NF, Indexe usw. Top. Trotzdem saulangsam...
... später hat er das unter Linux ausgeführt und da waren die Performanceprobleme auf einmal verschwunden. Wir vermuten, das irgendwas in Win/PHP in Zusammenarbeit mit MySQL eine gewaltige Performancebremse ist. |
Re: Wie MySQL-Abfrage optimieren? (große Tabelle, Dauer: 0.2
Hallo,
das habe ich auch schon festgestellt. Unter Windows sind die Abfragen bei mir ebenfalls deutlich langsamer als auf dem Linux-Webserver. Es wäre wirklich interessant zu wissen, woran das genau liegt. Grüße, Matze |
Re: Wie MySQL-Abfrage optimieren? (große Tabelle, Dauer: 0.2
Ich wollte letzt testweise mal die Kombination IIS, FastCGI, PHP, mySQL ausprobieren und schauen ob die schneller ist, aber leider leider wie immer zu wenig Zeit für solche Spielerein
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 03:14 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