Da Sie ein Kopfgeld aufbringen, werde ich meine hart erkämpften Geheimnisse teilen ...
Im Allgemeinen mussten für alle SQLs, die ich heute optimiert habe, Unterabfragen verwendet werden. Aus der Oracle-Datenbankwelt stammend, funktionierten Dinge, die ich für selbstverständlich hielt, mit MySQL nicht gleich. Und meine Lektüre über MySQL-Tuning lässt mich zu dem Schluss kommen, dass MySQL bei der Optimierung von Abfragen hinter Oracle steht.
Während die einfachen Abfragen, die für die meisten B2C-Anwendungen erforderlich sind, für MySQL gut funktionieren können, scheint der Großteil der für Intelligence Reporting erforderlichen aggregierten Berichterstellungstypen einiges an Planung und Neuorganisation der SQL-Abfragen zu erfordern, damit MySQL sie schneller ausführen kann.
Verwaltung:
max_connections
ist die Anzahl der gleichzeitigen Verbindungen. Der Standardwert ist 100 Verbindungen (151 seit 5.0) - sehr klein.
Hinweis:
Verbindungen beanspruchen Speicher und Ihr Betriebssystem kann möglicherweise nicht viele Verbindungen verarbeiten.
Mit MySQL-Binärdateien für Linux / x86 können Sie bis zu 4096 gleichzeitige Verbindungen herstellen, selbst kompilierte Binärdateien sind jedoch häufig weniger begrenzt.
Stellen Sie table_cache so ein, dass es mit der Anzahl Ihrer geöffneten Tabellen und gleichzeitigen Verbindungen übereinstimmt. Beobachten Sie den Wert von open_tables. Wenn er schnell wächst, müssen Sie ihn vergrößern.
Hinweis:
Die beiden vorherigen Parameter erfordern möglicherweise viele geöffnete Dateien. 20 + max_connections + table_cache * 2 ist eine gute Schätzung für das, was Sie benötigen. MySQL unter Linux verfügt über die Option open_file_limit. Legen Sie dieses Limit fest.
Wenn Sie komplexe Abfragen haben, sind sort_buffer_size und tmp_table_size wahrscheinlich sehr wichtig. Die Werte hängen von der Komplexität der Abfrage und den verfügbaren Ressourcen ab. Es werden jedoch 4 MB bzw. 32 MB als Ausgangspunkt empfohlen.
Hinweis: Dies sind "pro Verbindung" -Werte zwischen read_buffer_size, read_rnd_buffer_size und einigen anderen, was bedeutet, dass dieser Wert möglicherweise für jede Verbindung benötigt wird. Berücksichtigen Sie also Ihre Last und die verfügbare Ressource, wenn Sie diese Parameter einstellen. Beispielsweise wird sort_buffer_size nur zugewiesen, wenn MySQL eine Sortierung durchführen muss. Hinweis: Achten Sie darauf, dass Ihnen nicht der Speicher ausgeht.
Wenn Sie viele Verbindungen hergestellt haben (dh eine Website ohne dauerhafte Verbindungen), können Sie die Leistung verbessern, indem Sie thread_cache_size auf einen Wert ungleich Null setzen. 16 ist ein guter Wert für den Anfang. Erhöhen Sie den Wert, bis Ihre threads_created nicht mehr sehr schnell wachsen.
PRIMÄRSCHLÜSSEL:
Es kann nur eine AUTO_INCREMENT-Spalte pro Tabelle geben, sie muss indiziert sein und darf keinen DEFAULT-Wert haben
KEY ist normalerweise ein Synonym für INDEX. Das Schlüsselattribut PRIMARY KEY kann auch als nur KEY angegeben werden, wenn es in einer Spaltendefinition angegeben wird. Dies wurde aus Gründen der Kompatibilität mit anderen Datenbanksystemen implementiert.
Ein PRIMARY KEY ist ein eindeutiger Index, bei dem alle Schlüsselspalten als NOT NULL definiert werden müssen
Wenn ein PRIMARY KEY- oder UNIQUE-Index nur aus einer Spalte mit einem Integer-Typ besteht, können Sie die Spalte in SELECT-Anweisungen auch als "_rowid" bezeichnen.
In MySQL lautet der Name eines PRIMARY KEY PRIMARY
Derzeit unterstützen nur InnoDB-Tabellen (v5.1?) Fremdschlüssel.
Normalerweise erstellen Sie alle Indizes, die Sie beim Erstellen von Tabellen benötigen. Jede Spalte, die als PRIMARY KEY, KEY, UNIQUE oder INDEX deklariert ist, wird indiziert.
NULL bedeutet "keinen Wert haben". Zum Testen auf NULL können Sie keine arithmetischen Vergleichsoperatoren wie =, <oder <> verwenden. Verwenden Sie stattdessen die Operatoren IS NULL und IS NOT NULL:
NO_AUTO_VALUE_ON_ZERO unterdrückt das automatische Inkrement für 0, sodass nur NULL die nächste Sequenznummer generiert. Dieser Modus kann nützlich sein, wenn 0 in der Spalte AUTO_INCREMENT einer Tabelle gespeichert wurde. (Das Speichern von 0 wird übrigens nicht empfohlen.)
So ändern Sie den Wert des Zählers AUTO_INCREMENT, der für neue Zeilen verwendet werden soll:
ALTER TABLE mytable AUTO_INCREMENT = value;
oder SET INSERT_ID = Wert;
Sofern nicht anders angegeben, beginnt der Wert mit: 1000000 oder geben Sie ihn folgendermaßen an:
...) ENGINE = MyISAM DEFAULT CHARSET = latin1 AUTO_INCREMENT = 1
ZEITSTEMPEL:
Werte für TIMESTAMP-Spalten werden zum Speichern von der aktuellen Zeitzone in UTC und zum Abrufen von UTC in die aktuelle Zeitzone konvertiert.
http://dev.mysql.com/doc/refman/5.1/de/timestamp.html
Für eine TIMESTAMP-Spalte in einer Tabelle können Sie den aktuellen Zeitstempel als Standardwert und den Wert für die automatische Aktualisierung zuweisen.
Bei der Verwendung eines dieser Typen in einer WHERE-Klausel ist es am besten, WHERE datecolumn = FROM_UNIXTIME (1057941242) und nicht WHERE UNIX_TIMESTAMP (datecolumn) = 1057941242 zu verwenden. Letzteres nutzt keinen Index auf dieser Spalte.
http://dev.mysql.com/doc/refman/5.1/en/date-and-time-functions.html
UNIX_TIMESTAMP()
FROM_UNIXTIME()
UTC_DATE()
UTC_TIME()
UTC_TIMESTAMP()
Wenn Sie eine Datums- und Uhrzeitangabe in MySQL in einen Unix-Zeitstempel konvertieren:
Und dann 24 Stunden hinzufügen:
Und dann wieder in eine Datumszeit konvertieren, verliert sie auf magische Weise eine Stunde!
Hier ist was passiert. Bei der Konvertierung des Unix-Zeitstempels zurück in eine Datumszeit wird die Zeitzone berücksichtigt, und es kommt vor, dass wir zwischen dem 28. und 29. Oktober 2006 die Sommerzeit verloren haben und eine Stunde verloren haben.
Ab MySQL 4.1.3 geben die Funktionen CURRENT_TIMESTAMP (), CURRENT_TIME (), CURRENT_DATE () und FROM_UNIXTIME () Werte in der aktuellen Zeitzone der Verbindung zurück , die als Wert der Systemvariablen time_zone verfügbar ist. Außerdem geht UNIX_TIMESTAMP () davon aus, dass das Argument ein Datum / Uhrzeit-Wert in der aktuellen Zeitzone ist.
Die aktuelle Zeitzoneneinstellung wirkt sich nicht auf Werte aus, die von Funktionen wie UTC_TIMESTAMP () angezeigt werden, oder auf Werte in den Spalten DATE, TIME oder DATETIME.
HINWEIS: NUR BEI UPDATE aktualisiert die DateTime, wenn ein Feld geändert wird. Wenn ein UPDATE dazu führt, dass keine Felder geändert werden, wird die DateTime NICHT aktualisiert!
Zusätzlich ist der erste TIMESTAMP standardmäßig immer AUTOUPDATE, auch wenn er nicht angegeben ist
Wenn ich mit Datumsangaben arbeite, gehe ich fast immer zu Julian Date über, da Datenmathematik aus dem gleichen Grund eine einfache Angelegenheit ist, Ganzzahlen und Sekunden seit Mitternacht zu addieren oder zu subtrahieren. Es ist selten, dass ich eine zeitliche Auflösung mit einer feineren Granularität als Sekunden benötige.
Beide können als 4-Byte-Ganzzahl gespeichert werden, und wenn der Speicherplatz sehr knapp ist, können sie als vorzeichenlose Ganzzahl, die bis etwa 2106 gültig ist, in UNIX-Zeit (Sekunden seit der Epoche 01.01.1970) kombiniert werden als:
Sekunden in 24 Stunden = 86400
'Signed Integer max val = 2.147.483.647 - kann 68 Jahre von Sekunden halten
'Unsigned Integer max val = 4,294,967,295 - kann 136 Jahre von Sekunden halten
Binäres Protokoll:
Mit MySQL 4.1 wurde ein Binärprotokoll eingeführt, mit dem Datenwerte ohne Zeichenfolge im nativen Format gesendet und zurückgegeben werden können, ohne dass sie in das Zeichenfolgenformat konvertiert werden müssen. (Sehr hilfreich)
Außerdem ist mysql_real_query () schneller als mysql_query (), da strlen () nicht aufgerufen wird, um die Anweisungszeichenfolge zu bearbeiten.
http://dev.mysql.com/tech-resources/articles/4.1/prepared-statements.html
Das Binärprotokoll unterstützt serverseitig vorbereitete Anweisungen und ermöglicht die Übertragung von Datenwerten im nativen Format. Das Binärprotokoll wurde in früheren Versionen von MySQL 4.1 ziemlich überarbeitet.
Mit dem Makro IS_NUM () können Sie testen, ob ein Feld einen numerischen Typ hat. Übergeben Sie den Typwert an IS_NUM () und er wird als TRUE ausgewertet, wenn das Feld numerisch ist:
Eine Sache zu beachten ist , dass binäre Daten CAN innerhalb einer regelmäßigen Abfrage gesendet, wenn Sie es entkommen und erinnern MySQL erfordert nur , dass Backslash und die Anführungszeichen maskiert werden. Das ist also eine sehr einfache Möglichkeit, kürzere Binärzeichenfolgen wie beispielsweise verschlüsselte / gesalzene Passwörter einzufügen.
Master Server:
http://www.experts-exchange.com/Database/MySQL/Q_22967482.html
http://www.databasejournal.com/features/mysql/article.php/10897_3355201_2
GRANT REPLICATION SLAVE ON . to Slave_Benutzer IDENTIFIZIERT DURCH 'Slave_Password'
#Master Binary Logging Config STATEMENT causes replication
to be statement-based - default
log-bin=Mike
binlog-format=STATEMENT
server-id=1
max_binlog_size = 10M
expire_logs_days = 120
#Slave Config
master-host=master-hostname
master-user=slave-user
master-password=slave-password
server-id=2
Die binäre Protokolldatei muss lauten:
http://dev.mysql.com/doc/refman/5.0/en/binary-log.html
http://www.mydigitallife.info/2007/10/06/how-to-read-mysql-binary-log-files-binlog-with-mysqlbinlog/
http://dev.mysql.com/doc/refman/5.1/en/mysqlbinlog.html
http://dev.mysql.com/doc/refman/5.0/en/binary-log.html
http://dev.mysql.com/doc/refman/5.1/en/binary-log-setting.html
Sie können alle binären Protokolldateien mit der Anweisung RESET MASTER oder eine Teilmenge davon mit PURGE MASTER löschen
--result-file = binlog.txt TrustedFriend-bin.000030
Normalisierung:
http://dev.mysql.com/tech-resources/articles/intro-to-normalization.html
UDF-Funktionen
http://www.koders.com/cpp/fid10666379322B54AD41AEB0E4100D87C8CDDF1D8C.aspx
http://souptonuts.sourceforge.net/readme_mysql.htm
Datentypen:
http://dev.mysql.com/doc/refman/5.1/en/storage-requirements.html
http://www.informit.com/articles/article.aspx?p=1238838&seqNum=2
http://bitfilm.net/2008/03/24/saving-bytes-efficient-data-storage-mysql-part-1/
Zu beachten ist, dass mySQL in einer gemischten Tabelle mit CHAR und VARCHAR die CHARs in VARCHARs ändert
RecNum integer_type UNSIGNED NOT NULL AUTO_INCREMENT, PRIMARY KEY (RecNum)
MySQL repräsentiert immer Daten mit dem ersten Jahr gemäß den Standardspezifikationen von SQL und ISO 8601
Sonstiges:
Das Deaktivieren einiger MySQl-Funktionen führt zu kleineren Datendateien und einem schnelleren Zugriff. Beispielsweise:
--datadir gibt das Datenverzeichnis und an
--skip-innodb deaktiviert die inno-Option und spart Ihnen 10-20 Millionen
Mehr hier
http://dev.mysql.com/tech-resources/articles/mysql-c-api.html
Laden Sie Kapitel 7 - Kostenlos herunter
InnoDB ist eine Transaktion, aber damit verbunden ist ein Leistungsaufwand. Ich habe festgestellt, dass MyISAM-Tabellen für 90% meiner Projekte ausreichen. Nicht transaktionssichere Tabellen (MyISAM) haben mehrere eigene Vorteile, die alle auftreten, weil:
Es gibt keinen Transaktionsaufwand:
Viel schneller
Geringerer Speicherplatzbedarf
Für die Durchführung von Updates ist weniger Speicher erforderlich
Jede MyISAM-Tabelle wird in drei Dateien auf der Festplatte gespeichert. Die Dateien haben Namen, die mit dem Tabellennamen beginnen, und eine Erweiterung, die den Dateityp angibt. Eine .frm-Datei speichert das Tabellenformat. Die Datendatei hat die Erweiterung .MYD (MYData). Die Indexdatei hat die Erweiterung .MYI (MYIndex).
Diese Dateien können an einen intakten Speicherort kopiert werden, ohne die zeitaufwändige MySQL Administrators Backup-Funktion zu verwenden (ebenso die Wiederherstellung).
Der Trick besteht darin, eine Kopie dieser Dateien zu erstellen und dann die Tabelle zu löschen. Wenn Sie die Dateien zurücklegen, erkennt MySQl sie und aktualisiert die Tabellenverfolgung.
Wenn Sie sichern / wiederherstellen müssen,
Das Wiederherstellen einer Sicherung oder das Importieren aus einer vorhandenen Speicherauszugsdatei kann abhängig von der Anzahl der Indizes und Primärschlüssel, die Sie in jeder Tabelle haben, lange dauern. Sie können diesen Vorgang erheblich beschleunigen, indem Sie Ihre ursprüngliche Speicherauszugsdatei ändern, indem Sie sie wie folgt umgeben:
SET AUTOCOMMIT = 0;
SET FOREIGN_KEY_CHECKS=0;
.. your dump file ..
SET FOREIGN_KEY_CHECKS = 1;
COMMIT;
SET AUTOCOMMIT = 1;
Fügen Sie den SQL-Befehl SET AUTOCOMMIT = 0 hinzu, um die Geschwindigkeit des Neuladens erheblich zu erhöhen. am Anfang der Dump-Datei und fügen Sie das COMMIT hinzu; Befehl bis zum Ende.
Standardmäßig ist die automatische Festschreibung aktiviert. Dies bedeutet, dass jeder Einfügebefehl in der Speicherauszugsdatei als separate Transaktion behandelt und vor dem nächsten Start auf die Festplatte geschrieben wird. Wenn Sie diese Befehle nicht hinzufügen, kann das erneute Laden einer großen Datenbank in InnoDB viele Stunden dauern ...
Die maximale Größe einer Zeile in einer MySQL-Tabelle beträgt 65.535 Byte
Die effektive maximale Länge eines VARCHAR in MySQL 5.0.3 und höher = maximale Zeilengröße (65.535 Byte)
VARCHAR-Werte werden beim Speichern nicht aufgefüllt. Nachgestellte Leerzeichen bleiben erhalten, wenn Werte gemäß Standard-SQL gespeichert und abgerufen werden.
CHAR- und VARCHAR-Werte in MySQL werden unabhängig von nachgestellten Leerzeichen verglichen.
Die Verwendung von CHAR beschleunigt Ihren Zugriff nur, wenn der gesamte Datensatz eine feste Größe hat. Das heißt, wenn Sie ein Objekt mit variabler Größe verwenden, können Sie auch alle Objekte mit variabler Größe erstellen. Sie gewinnen keine Geschwindigkeit, wenn Sie ein CHAR in einer Tabelle verwenden, die auch ein VARCHAR enthält.
Das VARCHAR-Limit von 255 Zeichen wurde ab MySQL 5.0.3 auf 65535 Zeichen erhöht
Volltextsuchen werden nur für MyISAM-Tabellen unterstützt.
http://dev.mysql.com/doc/refman/5.0/en/fulltext-search.html
BLOB-Spalten haben keinen Zeichensatz, und Sortierung und Vergleich basieren auf den numerischen Werten der Bytes in Spaltenwerten
Wenn der strikte SQL-Modus nicht aktiviert ist und Sie einer BLOB- oder TEXT-Spalte einen Wert zuweisen, der die maximale Länge der Spalte überschreitet, wird der Wert passend abgeschnitten und eine Warnung generiert.
Nützliche Befehle:
Überprüfen Sie den strengen Modus: SELECT @@ global.sql_mode;
Strengen Modus ausschalten:
SET @@ global.sql_mode = '';
SET @@ global.sql_mode = 'MYSQL40'
oder entfernen: sql-mode = "STRICT_TRANS_TABLES, ...
SHOW COLUMNS FROM mytable
SELECT max (namecount) AS virtualcolumn
FROM mytable ORDER BY virtualcolumn
http://dev.mysql.com/doc/refman/5.0/en/group-by-hidden-fields.html
http://dev.mysql.com/doc/refman/5.1/de/information-functions.html#function_last-insert-id
last_insert_id ()
Ruft die PK der letzten Zeile ab, die in den aktuellen Thread eingefügt wurde. max (pkcolname) Erhält die letzte PK insgesamt.
Hinweis: Wenn die Tabelle leer ist, gibt max (pkcolname) 1 zurück. Mysql_insert_id () konvertiert den Rückgabetyp der nativen MySQL C-API-Funktion mysql_insert_id () in einen Long-Typ (in PHP int genannt).
Wenn Ihre AUTO_INCREMENT-Spalte den Spaltentyp BIGINT hat, ist der von mysql_insert_id () zurückgegebene Wert falsch. Verwenden Sie stattdessen die interne MySQL SQL-Funktion LAST_INSERT_ID () in einer SQL-Abfrage.
http://dev.mysql.com/doc/refman/5.0/de/information-functions.html#function_last-insert-id
Nur ein Hinweis: Wenn Sie versuchen, Daten in eine Tabelle einzufügen, wird folgende Fehlermeldung angezeigt:
Unknown column ‘the first bit of data what you want to put into the table‘ in ‘field list’
mit so etwas wie
INSERT INTO table (this, that) VALUES ($this, $that)
Das liegt daran, dass Sie keine Apostrophe um die Werte haben, die Sie in die Tabelle einfügen möchten. Sie sollten Ihren Code also ändern in:
INSERT INTO table (this, that) VALUES ('$this', '$that')
daran erinnern, dass `` verwendet werden, um MySQL-Felder, Datenbanken oder Tabellen zu definieren, keine Werte;)
Verbindung zum Server während der Abfrage verloren:
http://dev.mysql.com/doc/refman/5.1/en/gone-away.html
http://dev.mysql.com/doc/refman/5.1/en/packet-too-large.html
http://dev.mysql.com/doc/refman/5.0/en/server-parameters.html
http://dev.mysql.com/doc/refman/5.1/en/show-variables.html
http://dev.mysql.com/doc/refman/5.1/en/option-files.html
http://dev.mysql.com/doc/refman/5.1/en/error-log.html
Abfragen optimieren
http://www.artfulsoftware.com/infotree/queries.php?&bw=1313
Nun, das sollte ausreichen, um den Bonus zu verdienen, den ich denke ... Die Früchte vieler Stunden und vieler Projekte mit einer großartigen kostenlosen Datenbank. Ich entwickle Anwendungsdatenserver auf Windows-Plattformen hauptsächlich mit MySQL. Das schlimmste Durcheinander, das ich beseitigen musste, war
Der ultimative Alptraum für MySQL-Legacy-Datenbanken
Dies erforderte eine Reihe von Anwendungen, um die Tabellen mit vielen der hier genannten Tricks zu etwas Nützlichem zu verarbeiten.
Wenn Sie dies erstaunlich hilfreich fanden, drücken Sie Ihren Dank aus, indem Sie es abstimmen.
Lesen Sie auch meine anderen Artikel und Whitepaper unter: www.coastrd.com