Wie können Sie die MySQL-Leistung mit den aktuellen Serverressourcen steigern?

7

Ich habe eine MySQL-Datenbank und einige meiner Abfragen wurden langsam. Die Abfragezeit ist nicht stabil. Die meisten Abfragen sind schnell, aber einige von ihnen (möglicherweise lesen und geben weniger Daten zurück) dauern lange.

Ich weiß, dass Best Practices das Hinzufügen von Indizes oder Refactor-Code sind, aber ich habe bereits Indizes hinzugefügt und möchte Code nicht refactorisieren (zumindest solange ich andere Varianten habe).

Ich habe 8 GB freien Speicher und die CPU ist zu Spitzenzeiten nur zu 25% ausgelastet. Ich möchte also alle meine Ressourcen nutzen.

Ich versuche, die MySQL-Konfiguration zu optimieren, habe aber noch keine Erfahrung mit solchen Optimierungen. Daher erhöhe ich die Produktivität nicht so sehr, wie ich es möchte. Hier ist ein Beispiel:

# Query_time: 3.019647  Lock_time: 0.000000 Rows_sent: 1  Rows_examined: 504
SET timestamp=1313380874;
SELECT COUNT(inboxentities.id) FROM inboxentities  WHERE (active=true)AND(deleted=false)AND((to_ = '44219ca4-a657-4909-b30d-a7ba0ed8e4b0'))AND(notification=true);

PS inboxentitieshat 500.000 Datensätze. Ich habe index1 (idx_to): to_und index2 (idx_complex): deleted, notification, active,to_

Hier ist das Ergebnis von EXPLAIN Select:

+----+-------------+---------------+------+------------------------------------------------+--------+---------+-------+------+-------------+
| id | select_type | table         | type | possible_keys                                  | key    | key_len | ref   | rows | Extra       |
+----+-------------+---------------+------+------------------------------------------------+--------+---------+-------+------+-------------+
|  1 | SIMPLE      | inboxentities | ref  | idx_status,idx_statusToname,idx_to,idx_complex | idx_to | 768     | const |  286 | Using where |
+----+-------------+---------------+------+------------------------------------------------+--------+---------+-------+------+-------------+
Xupypr MV
quelle
Ich bin kein MySQL-Experte, aber 3 Sekunden, um 500 Zeilen zu untersuchen, scheinen sehr lang zu sein. Wie ist die E / A auf Ihrem System?
Matthew Watson
Es gibt viele Abfragen gleichzeitig. Das System ist Hochlast. Ich möchte also mehr Serverressourcen verwenden. Das E / A-Diagramm zeigt keine Spitzen oder Überlastungen.
Xupypr MV
Aber meine Datenbankgröße beträgt weniger als 5 GB. Ich denke, es ist schön, alle Daten im Speicher zwischenzuspeichern, aber das ist jetzt nicht möglich. Oder kann es sein, dass es kein guter Ansatz ist?
Xupypr MV
25%? Sind Sie auf einer Quad-Core-Maschine? Es klingt so, als würde es einen Kern zu 100% treffen. Sie befinden sich nicht im Single-Thread-Modus , oder?
Richard
@ Richard Ich habe keinen Schlüssel --one-threadin meiner Konfiguration. Auch ich habe thread_concurrency = 8Option.
Xupypr MV

Antworten:

6

Hier ist Ihre ursprüngliche Abfrage aus dem langsamen Protokoll

SELECT COUNT(inboxentities.id) FROM inboxentities
WHERE (active=true)
AND (deleted=false)
AND ((to_ = '44219ca4-a657-4909-b30d-a7ba0ed8e4b0'))
AND (notification=true);

Der effektivste Weg, eine Abfrage wie diese zu indizieren, besteht darin, einen Index zu generieren, der so viele Felder wie möglich in der WHERE-Klausel abdeckt. Ein Index, der unter Berücksichtigung dieses Konzepts erstellt wurde, wird als Deckungsindex bezeichnet .

Schauen Sie sich die WHERE-Klausel an

  • 'aktiv' ist wahr oder falsch (2 Werte). Ein Index nur dieses Feldes ist schief.
  • 'gelöscht' ist wahr oder falsch (2 Werte). Ein Index nur dieses Feldes ist schief.
  • 'Benachrichtigung' ist wahr oder falsch (2 Werte). Ein Index nur dieses Feldes ist schief.
  • 'to_' ist ein Wert, der es wert ist, indiziert und eingegrenzt zu werden.

Obwohl Sie idx_complex definiert haben, enthält die Abfrage ein weiteres Element, das dazu führt, dass der idx_complex-Index nicht verwendet wird: die COUNT- Klausel (inboxentities.id) .

Sie zählen etwas in einer Tabelle. Der Index hat keinen Referenzpunkt auf die Tabelle außer to_. Der MySQL Query Optmizer würde idx_to, den einfachsten Index, auswählen. Um das MySQL Query Optimizer zu zwingen, den gewünschten Abdeckungsindex (idx_complex) auszuwählen, zählen Sie einfach COUNT aus dem Index und nicht aus der Tabelle. Mein Vorschlag ist, die Abfrage leicht zu ändern:

SELECT COUNT(to_) FROM inboxentities
WHERE (active=true)
AND (deleted=false)
AND ((to_ = '44219ca4-a657-4909-b30d-a7ba0ed8e4b0'))
AND (notification=true);

Versuche es !!!

UPDATE 15.08.2011 15:16 EDT

Einige haben geringfügige bis signifikante Leistungssteigerungen festgestellt, indem sie my.cnf geändert haben, um die Leistungsanforderungen von Storage Engine zu erfüllen.

Sie müssen den MyISAM-Schlüsselcache und den InnoDB-Pufferpool festlegen.

Dies empfiehlt die richtige Größe des MyISAM-Schlüsselcaches für Ihren angegebenen Datensatz:

SELECT CONCAT(ROUND(KBS/POWER(1024,
IF(PowerOf1024<0,0,IF(PowerOf1024>3,0,PowerOf1024)))+0.4999),
SUBSTR(' KMG',IF(PowerOf1024<0,0,
IF(PowerOf1024>3,0,PowerOf1024))+1,1))
recommended_key_buffer_size FROM
(SELECT LEAST(POWER(2,32),KBS1) KBS
FROM (SELECT SUM(index_length) KBS1
FROM information_schema.tables
WHERE engine='MyISAM' AND
table_schema NOT IN ('information_schema','mysql')) AA ) A,
(SELECT 2 PowerOf1024) B;

Dadurch wird der InnoDB-Pufferpool mit der richtigen Größe für Ihren angegebenen Datensatz empfohlen

SELECT CONCAT(ROUND(KBS/POWER(1024,
IF(PowerOf1024<0,0,IF(PowerOf1024>3,0,PowerOf1024)))+0.49999),
SUBSTR(' KMG',IF(PowerOf1024<0,0,
IF(PowerOf1024>3,0,PowerOf1024))+1,1)) recommended_innodb_buffer_pool_size
FROM (SELECT SUM(data_length+index_length) KBS FROM information_schema.tables
WHERE engine='InnoDB') A,
(SELECT 2 PowerOf1024) B;

Übrigens

  • (SELECT 0 PowerOf1024) generiert die Antwort in Bytes
  • (SELECT 1 PowerOf1024) generiert die Antwort in KB
  • (SELECT 2 PowerOf1024) generiert die Antwort in MB
  • (SELECT 3 PowerOf1024) generiert die Antwort in GB

Wenn Sie darüber hinausgehen, senden Sie mir eine E-Mail.

Wenn Sie diese Einstellungen vorgenommen haben, stellen Sie sicher, dass die kombinierte Anzahl für empfohlene_Schlüsselpuffergröße und empfohlene_Bundpuffer_Poolgröße 75% des installierten Arbeitsspeichers nicht überschreitet.

UPDATE 15.08.2011 15:35 EDT

Möglicherweise möchten Sie mysqltuner.pl auf dem Server ausführen, damit Sie erfahren, wie Sie die Speicherauslastung für DB Connections tweeken. Zu den Einstellungen für die Speichernutzung pro DB-Verbindung gehören:

Diese werden normalerweise mit max_connections multipliziert .

Sie können mysqltuner.pl wie folgt über die Linux-Befehlszeile herunterladen:

wget mysqltuner.pl

Die Ausgabe davon ist ungefähr so:

$ perl mysqltuner.pl

 >>  MySQLTuner 1.2.0 - Major Hayden <major@mhtx.net>
 >>  Bug reports, feature requests, and downloads at http://mysqltuner.com/
 >>  Run with '--help' for additional options and output filtering
Please enter your MySQL administrative login: username
Please enter your MySQL administrative password: (password hidden)

-------- General Statistics --------------------------------------------------
[--] Skipped version check for MySQLTuner script
[OK] Currently running supported MySQL version 5.1.47-community-log
[OK] Operating on 64-bit architecture

-------- Storage Engine Statistics -------------------------------------------
[--] Status: +Archive -BDB -Federated +InnoDB -ISAM -NDBCluster
[--] Data in MyISAM tables: 7G (Tables: 6)
[--] Data in InnoDB tables: 2G (Tables: 382)
[!!] Total fragmented tables: 84

-------- Security Recommendations  -------------------------------------------
[OK] All database users have passwords assigned

-------- Performance Metrics -------------------------------------------------
[--] Up for: 12d 20h 24m 6s (54M q [49.462 qps], 555K conn, TX: 287B, RX: 95B)
[--] Reads / Writes: 62% / 38%
[--] Total buffers: 9.3G global + 48.2M per thread (1250 max threads)
[!!] Maximum possible memory usage: 68.2G (291% of installed RAM)
[OK] Slow queries: 0% (647/54M)
[OK] Highest usage of available connections: 5% (69/1250)
[OK] Key buffer size / total MyISAM indexes: 256.0M/19.4M
[OK] Key buffer hit rate: 100.0% (51M cached / 10 reads)
[OK] Query cache efficiency: 89.3% (47M cached / 52M selects)
[!!] Query cache prunes per day: 60670
[OK] Sorts requiring temporary tables: 0% (239 temp sorts / 1M sorts)
[!!] Temporary tables created on disk: 47% (1M on disk / 2M total)
[OK] Thread cache hit rate: 99% (103 created / 555K connections)
[OK] Table cache hit rate: 21% (722 open / 3K opened)
[OK] Open file limit used: 0% (70/32K)
[OK] Table locks acquired immediately: 99% (12M immediate / 12M locks)
[OK] InnoDB data size / buffer pool: 2.4G/8.0G

-------- Recommendations -----------------------------------------------------
General recommendations:
    Run OPTIMIZE TABLE to defragment tables for better performance
    Reduce your overall MySQL memory footprint for system stability
    Increasing the query_cache size over 128M may reduce performance
    When making adjustments, make tmp_table_size/max_heap_table_size equal
    Reduce your SELECT DISTINCT queries without LIMIT clauses
Variables to adjust:
  *** MySQL's maximum memory usage is dangerously high ***
  *** Add RAM before increasing MySQL buffer variables ***
    query_cache_size (> 1G) [see warning above]
    tmp_table_size (> 32M)
    max_heap_table_size (> 32M)
RolandoMySQLDBA
quelle
Klingt wie eine gute Idee. Ich werde es morgen versuchen.
Xupypr MV
Es ist jedoch nicht nur eine Art von Anforderungen, die langsam sind. Es ist nicht gut, sie alle aufzulösen (einige von ihnen können nicht auf diese Weise optimiert werden, z. B. Anfragen, die große Datenmengen abrufen, oder Volltextsuche). Können Sie meine ursprüngliche Frage beantworten? Kann ich alle meine kostenlosen Ressourcen für MySQL verwenden? (oder sag mir, dass ich falsch liege und mit diesem Ansatz nicht schneller werde).
Xupypr MV