Frage

Da dies mein erster Beitrag ist es scheint, dass ich nur 1 Link veröffentlichen kann, damit ich die Websites aufgeführt haben beziehe ich mich auf dem Boden. Auf den Punkt gebracht ist mein Ziel, die Datenbank geben die Ergebnisse schneller zu machen, ich habe so viele relevante Informationen aufzunehmen versucht, als ich von zu Hilfe Rahmen die Fragen am Ende des Post denken konnte.

Maschinen-Info


8 processors
model name      : Intel(R) Xeon(R) CPU           E5440  @ 2.83GHz
cache size      : 6144 KB
cpu cores       : 4 

top - 17:11:48 up 35 days, 22:22, 10 users,  load average: 1.35, 4.89, 7.80
Tasks: 329 total,   1 running, 328 sleeping,   0 stopped,   0 zombie
Cpu(s):  0.0%us,  0.0%sy,  0.0%ni, 87.4%id, 12.5%wa,  0.0%hi,  0.0%si,  0.0%st
Mem:   8173980k total,  5374348k used,  2799632k free,    30148k buffers
Swap: 16777208k total,  6385312k used, 10391896k free,  2615836k cached

Jedoch bei suchen wir die MySQL-Installation auf einem anderen Rechner im Cluster zu bewegen, die 256 GB RAM

Table Info


Meine MySQL-Tabelle sieht aus wie

CREATE TABLE ClusterMatches 
(
    id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
    cluster_index INT, 
    matches LONGTEXT,
    tfidf FLOAT,
    INDEX(cluster_index)   
);

Es hat etwa 18M Reihen gibt es 1M einzigartige cluster_index ist und 6K einzigartige Begegnungen. Die SQL-Abfrage, die ich in PHP bin Erzeugung aussieht.

SQL-Abfrage


$sql_query="SELECT `matches`,sum(`tfidf`) FROM 
(SELECT * FROM Test2_ClusterMatches WHERE `cluster_index` in (".$clusters.")) 
AS result GROUP BY `matches` ORDER BY sum(`tfidf`) DESC LIMIT 0, 10;";

Dabei steht $ Cluster eine Reihe von etwa 3.000 Komma enthält getrennt cluster_index ist. Diese Abfrage macht von ca. 50.000 Zeilen und dauert etwa 15 Sekunden zu laufen, wenn die gleiche Abfrage erneut ausgeführt wird es dauert 1s ungefähr zu laufen.

Verwendung


  1. Der Inhalt der Tabelle kann angenommen werden, statisch sein.
  2. Niedrige Anzahl gleichzeitiger Benutzer
  3. Die Abfrage oben ist derzeit die einzige Abfrage, die auf dem Tisch ausgeführt werden

Subquery


Basierend auf diesen Beitrag [Stackoverflow: Cache / Re-Use eine Unterabfrage in MySQL]. [1] und die Verbesserung der Abfrage, wenn ich meine subquery glauben indiziert werden kann

mysql> EXPLAIN EXTENDED SELECT `matches`,sum(`tfidf`) FROM 
(SELECT * FROM ClusterMatches WHERE `cluster_index` in (1,2,...,3000) 
AS result GROUP BY `matches` ORDER BY sum(`tfidf`) ASC LIMIT 0, 10;

+----+-------------+----------------------+-------+---------------+---------------+---------+------+-------+---------------------------------+
| id | select_type | table                | type  | possible_keys | key           | key_len | ref  | rows  | Extra                           |
+----+-------------+----------------------+-------+---------------+---------------+---------+------+-------+---------------------------------+
|  1 | PRIMARY     |  derived2            | ALL   | NULL          | NULL          | NULL    | NULL | 48528 | Using temporary; Using filesort | 
|  2 | DERIVED     | ClusterMatches       | range | cluster_index | cluster_index | 5       | NULL | 53689 | Using where                     | 
+----+-------------+----------------------+-------+---------------+---------------+---------+------+-------+---------------------------------+

Nach diesem älteren Artikel [Optimizing MySQL: Abfragen und Indizes] [2] in Zusätzlichen Informationen - die schlechten hier zu sehen sind, „kann vorübergehend“ und „mit filesort“

MySQL-Konfigurations-Info


Abfrage-Cache zur Verfügung steht, aber effektiv wie die Größe zur Zeit ausgeschaltet wird auf Null gesetzt


mysqladmin variables;
+---------------------------------+----------------------+
| Variable_name                   | Value                |
+---------------------------------+----------------------+
| bdb_cache_size                  | 8384512              | 
| binlog_cache_size               | 32768                | 
| expire_logs_days                | 0                    |
| have_query_cache                | YES                  | 
| flush                           | OFF                  |
| flush_time                      | 0                    |
| innodb_additional_mem_pool_size | 1048576              |
| innodb_autoextend_increment     | 8                    |
| innodb_buffer_pool_awe_mem_mb   | 0                    |
| innodb_buffer_pool_size         | 8388608              |
| join_buffer_size                | 131072               |
| key_buffer_size                 | 8384512              |
| key_cache_age_threshold         | 300                  |
| key_cache_block_size            | 1024                 |
| key_cache_division_limit        | 100                  |
| max_binlog_cache_size           | 18446744073709547520 | 
| sort_buffer_size                | 2097144              |
| table_cache                     | 64                   | 
| thread_cache_size               | 0                    | 
| query_cache_limit               | 1048576              |
| query_cache_min_res_unit        | 4096                 |
| query_cache_size                | 0                    |
| query_cache_type                | ON                   |
| query_cache_wlock_invalidate    | OFF                  |
| read_rnd_buffer_size            | 262144               |
+---------------------------------+----------------------+

Auf der Grundlage dieses Artikels auf [Mysql Datenbank-Performance Wende] [3] Ich glaube, dass die Werte, die ich zu zwicken müssen, sind

  1. table_cache
  2. key_buffer
  3. sort_buffer
  4. read_buffer_size
  5. record_rnd_buffer (für GROUP BY und ORDER BY Begriffe)

Bereiche für Verbesserungen identifiziert - MySQL Query zwickt


  1. Ändern der Datentyp für die Spiele zu einem Index, der einen int zeigt auf eine andere Tabelle ist [MySQL wird in der Tat eine dynamische Zeilenformat verwenden, wenn es Felder variabler Länge wie TEXT oder BLOB enthält, die in diesem Fall Mittel Bedürfnisse Sortierung sein auf der Festplatte durchgeführt. Die Lösung wird nicht, diese Datentypen zu vermeiden, sondern solche Felder in eine zugehörige Tabelle abzuspalten.] [4]
  2. die neue match_index Indizierung Feild, so dass die GROUP BY matches schneller auftritt, auf der Grundlage der Erklärung [ „Sie sollten wahrscheinlich Indizes für jedes Feld erstellen, auf dem Sie die Auswahl, Gruppierung, Bestellung, oder verbinden.“] [5]

Werkzeuge


zwicken ausführen ich plane verwenden

  1. [Explain] [6] unter Bezugnahme auf [das Ausgabeformat] [7]
  2. [ab - Apache HTTP Server-Benchmarking-Tool] [8]
  3. [Profilieren] [9] mit [Protokolldaten] [10]

Future Datenbankgröße


Das Ziel ist es, ein System aufzubauen, die 1M einzigartigen cluster_index Werte 1M eindeutige Übereinstimmung Werte, ca. 3 Mrd. Tabellenzeilen mit einer Reaktionszeit auf die Abfrage von etwa 0,5 s haben kann (wir können bei Bedarf mehr RAM hinzufügen und die Datenbank verteilen über der Cluster)

Fragen


  1. Ich denke, wir den gesamten Re-Cord in ram behalten wollen, so dass die Abfrage die Scheibe berühren tut, wenn wir die gesamte Datenbank im MySQL-Cache zu halten ist, dass die Notwendigkeit für memcachedb beseitigen?
  2. versucht, die gesamte Datenbank in MySQL-Cache eine schlechte Strategie zu halten, wie es ist nicht persistent zu sein entworfen? Wäre so etwas wie memcachedb oder redis ein besserer Ansatz, wenn ja, warum?
  3. Ist die temporäre Tabelle „Ergebnis“, die von der Abfrage automatisch erstellt wird, wenn die Abfrage beendet zerstört?
  4. Should wechseln wir von InnoDB MyISAM [als gut für Lese schweren data, wo als InnoDB ist gut für Schreib schwer] [11]?
  5. mein Cache doesnt zu sein scheint auf als Null in meiner [Abfrage Cache-Konfiguration] [12], warum die Abfrage zur Zeit auftritt schneller das zweite Mal, dass ich es laufen?
  6. kann ich restrukturieren meine Abfrage „können vorübergehend“ zu beseitigen und „mit filesort“ auftritt, sollte ich eine Verknüpfung statt einer Unterabfrage verwenden?
  7. Wie sehen Sie die Größe des MySQL [Data Cache] [13]?
  8. , welche Art von Größen für die Werte table_cache, key_buffer, sort_buffer, read_buffer_size, record_rnd_buffer würden Sie vorschlagen, die als Ausgangspunkt?

Links


  • 1: stackoverflow.com/questions/658937/cache-re-use-a-subquery-in-mysql
  • 2: databasejournal.com/features/mysql/article.php/10897_1382791_4/Optimizing-MySQL-Queries-and-Indexes.htm
  • 3: debianhelp.co.uk/mysqlperformance.htm
  • 4: 20bits.com/articles/10-tips-for-optimizing-mysql-queries-that-dont-suck /
  • 5: 20bits.com/articles/10-tips-for-optimizing-mysql-queries-that-dont-suck /
  • 6: dev.mysql.com/doc/refman/5.0/en/explain.html
  • 7: dev.mysql.com/doc/refman/5.0/en/explain-output.html
  • 8: httpd.apache.org/docs/2.2/programs/ab.html
  • 9: mtop.sourceforge.net /
  • 10: dev.mysql.com/doc/refman/5.0/en/slow-query-log.html
  • 11: 20bits.com/articles/10-tips-for-optimizing-mysql-queries-that-dont-suck /
  • 12: dev.mysql.com/doc/refman/5.0/en/query-cache-configuration.html
  • 13: dev.mysql.com/tech-resources/articles/mysql-query-cache.html
War es hilfreich?

Lösung

Ändern der Tabelle


Basierend auf dem Rat in diesem Beitrag auf Wie Indizes wählen vorbei und Gruppe von Abfragen nun die Tabelle aussieht

CREATE TABLE ClusterMatches 
(
    cluster_index INT UNSIGNED, 
    match_index INT UNSIGNED,
    id INT NOT NULL AUTO_INCREMENT,
    tfidf FLOAT,
    PRIMARY KEY (match_index,cluster_index,id,tfidf)
);
CREATE TABLE MatchLookup 
(
    match_index INT UNSIGNED NOT NULL PRIMARY KEY,
    image_match TINYTEXT
);

Die Beseitigung Subquery

Die Abfrage, ohne die Ergebnisse durch die SUM (TFIDF) Sortierung aussieht

SELECT match_index, SUM(tfidf) FROM ClusterMatches 
WHERE cluster_index in (1,2,3 ... 3000) GROUP BY match_index LIMIT 10;

Welche Verwendung von temporären und Verwendung beseitigt filesort

explain extended SELECT match_index, SUM(tfidf) FROM ClusterMatches 
WHERE cluster_index in (1,2,3 ... 3000) GROUP BY match_index LIMIT 10;
+----+-------------+----------------------+-------+---------------+---------+---------+------+-------+--------------------------+
| id | select_type | table                | type  | possible_keys | key     | key_len | ref  | rows  | Extra                    |
+----+-------------+----------------------+-------+---------------+---------+---------+------+-------+--------------------------+
|  1 | SIMPLE      | ClusterMatches       | range | PRIMARY       | PRIMARY | 4       | NULL | 14938 | Using where; Using index | 
+----+-------------+----------------------+-------+---------------+---------+---------+------+-------+--------------------------+

Sorting Problem

Allerdings, wenn ich die ORDER BY SUM (tfdif) Addiere

SELECT match_index, SUM(tfidf) AS total FROM ClusterMatches
WHERE cluster_index in (1,2,3 ... 3000) GROUP BY match_index 
ORDER BY total DESC LIMIT 0,10;
+-------------+--------------------+
| match_index | total              |
+-------------+--------------------+
|         868 |   0.11126546561718 | 
|        4182 | 0.0238558370620012 | 
|        2162 | 0.0216601379215717 | 
|        1406 | 0.0191618576645851 | 
|        4239 | 0.0168981291353703 | 
|        1437 | 0.0160425212234259 | 
|        2599 | 0.0156466849148273 | 
|         394 | 0.0155945559963584 | 
|        3116 | 0.0151005545631051 | 
|        4028 | 0.0149106932803988 | 
+-------------+--------------------+
10 rows in set (0.03 sec)

Das Ergebnis ist in geeigneter Weise schnell in diesem Maßstab, jedoch mit der ORDER BY SUM (TFIDF) Mittel verwendet es Temporär filesort

explain extended SELECT match_index, SUM(tfidf) AS total FROM ClusterMatches 
WHERE cluster_index IN (1,2,3 ... 3000) GROUP BY match_index 
ORDER BY total DESC LIMIT 0,10;
+----+-------------+----------------------+-------+---------------+---------+---------+------+-------+-----------------------------------------------------------+
| id | select_type | table                | type  | possible_keys | key     | key_len | ref  | rows  | Extra                                                     |
+----+-------------+----------------------+-------+---------------+---------+---------+------+-------+-----------------------------------------------------------+
|  1 | SIMPLE      | ClusterMatches       | range | PRIMARY       | PRIMARY | 4       | NULL | 65369 | Using where; Using index; Using temporary; Using filesort | 
+----+-------------+----------------------+-------+---------------+---------+---------+------+-------+-----------------------------------------------------------+

Mögliche Lösungen?

Im Suche nach einer Lösung, die nicht nur vorübergehend oder filesort nicht verwendet, entlang der Linien von

SELECT match_index, SUM(tfidf) AS total FROM ClusterMatches 
WHERE cluster_index IN (1,2,3 ... 3000) GROUP BY cluster_index, match_index 
HAVING total>0.01 ORDER BY cluster_index;
wo ich nicht brauchen einen Schwellenwert für insgesamt hart codieren, irgendwelche Ideen?

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top