2016-12-31 5 views
0

Ich habe dieses Schema, das Chat-Nachrichten speichert. Derzeit habe ich ungefähr 100k Zeilen, was etwa 5,5 MB Daten ist. Die Indexgröße beträgt 6,5 MB. Wenn die Datengröße ~ 4MB war, war die Indexgröße ~ 3MB, also wächst sie exponentiell?Tabelle zum Reduzieren der Indexgröße optimieren

CREATE TABLE `messages` (
    `id` int(10) unsigned NOT NULL AUTO_INCREMENT, 
    `author` int(11) unsigned DEFAULT NULL, 
    `time` int(10) unsigned DEFAULT NULL, 
    `text` text, 
    `dest` int(11) unsigned DEFAULT NULL, 
    `type` tinyint(4) unsigned DEFAULT NULL, 
    PRIMARY KEY (`id`), 
    KEY `history` (`author`,`dest`,`id`) USING BTREE, 
    KEY `messages_ibfk_1` (`dest`), 
    FULLTEXT KEY `msg` (`text`), 
    CONSTRAINT `au` FOREIGN KEY (`author`) REFERENCES `users` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, 
    CONSTRAINT `messages_ibfk_1` FOREIGN KEY (`dest`) REFERENCES `users` (`id`) ON DELETE CASCADE ON UPDATE CASCADE 
) ENGINE=InnoDB AUTO_INCREMENT=105895 DEFAULT CHARSET=utf8; 

Die Hauptabfrage, die ich für diese Tabelle renne und ich habe versucht, es zu optimieren für ist, wenn ich paginierte Geschichte für einen Chat zwischen 2 Personen

SELECT id, time, text, dest, type, author 
FROM `messages` 
WHERE (
    (author = ? AND dest = ?) OR (author = ? AND dest = ?) 
) AND id <= ? ORDER BY id DESC LIMIT ?, 25 

Das zeigen müssen Andere Abfragen für den Verlauf sind identisch, außer dass sie zusätzliche Filter für einen Suchbegriff oder einen Datumsbereich enthalten.

Gibt es etwas, das getan werden kann, um die Indexgröße zu reduzieren und eine optimale Leistung aufrechtzuerhalten?

+0

Warum denken Sie, dass die Indexgröße etwas mit Leistung zu tun hat? Laufen Ihre Abfragen langsam? Wenn Sie keine Indizes hätten, würden Sie zwar viel Speicherplatz sparen, aber Ihre Abfragen wären viel langsamer, also ist es offensichtlich, dass ein Index einen Platz-Performance-Kompromiss darstellt und Sie den Index überhaupt haben Ich habe den Wunsch geäußert, Leistung auf Kosten des Weltraums zu haben. –

+0

Ihr Index ist möglicherweise größer als die Tabelle selbst, wenn MySQL in Erwartung zukünftiger Einsätze etwas freien Speicherplatz im btree belässt. –

+0

Übrigens könnten Sie die Größe Ihres Indexes verringern und die Abfrageleistung verbessern, indem Sie "user1" und "user2" anstelle von "author" und "dest" speichern, die beiden Benutzer alphabetisch anordnen und "user1" zum ersten Benutzer machen "user2" der zweite. Wenn Sie also Gespräche zwischen Mark und Alice finden möchten, ist Alice immer "Benutzer1" und Mark wird immer "Benutzer2". Dann können Sie eine weitere Spalte hinzufügen, um anzugeben, ob "Benutzer1" der Autor oder Empfänger ist. –

Antwort

1

Mach dir keine Sorgen über das Wachstum der Indizes. Es ist wahrscheinlich ein Zufall; sicherlich nicht "exponentiell".

das Hauptproblem Unter der Annahme, ist die Leistung von

SELECT id, time, text, dest, type, author 
FROM `messages` 
WHERE (
    (author = ? AND dest = ?) OR (author = ? AND dest = ?) 
) AND id <= ? ORDER BY id DESC LIMIT ?, 25 

Ich sehe drei Techniken, die erheblich dazu beitragen wird: Veränderung OR-UNION, beschäftigen sich mit LIMIT in UNION, und sie OFFSET nicht für Paginierung verwenden.

 (SELECT id, time, text, dest, type, author 
      FROM `messages` 
      WHERE author = ? -- one author & dest 
       AND dest = ? 
       AND id < ? -- where you "left off" 
      ORDER BY id DESC 
      LIMIT 25 
     ) UNION ALL 
     (SELECT id, time, text, dest, type, author 
      FROM `messages` 
      WHERE author = ? -- the other author & dest 
       AND dest = ? 
       AND id < ?  -- same as above 
      ORDER BY id DESC 
      LIMIT 25 
     ) 
     ORDER BY id DESC 
     LIMIT 25;   -- get the desired 25 from the 50 above 

Pagination discussion erklärt, warum die OFFSET sollte entfernt werden. Es behandelt andere Techniken, einschließlich der Verwendung von 26 (an allen drei Stellen) anstelle von 25, so dass Sie wissen, ob dies die "letzte" Seite ist.

In der ersten Iteration könnte AND id < ? weggelassen werden. Oder (einfacher) könnten Sie eine sehr große Zahl ersetzen.

Ihr Index (author, dest, id) ist optimal für meine Erstellung.

Diese komplexe Formulierung wird leuchten, wenn messages größer wird und/oder die Benutzerseiten weiter durch die Liste.

+0

Diese Formulierung berührt maximal 50 Zeilen (plus Schreiben von 50 an tmp und erneutes Lesen von 50), unabhängig von der Tabellengröße oder Seitennummer. Die ursprüngliche Formulierung hat immer die meisten oder alle Zeilen berührt. –

+0

Vielen Dank für diese Antwort, es war sehr hilfreich - vor allem der Teil über die Vermeidung von Offset für Paginierung, ich habe in der Vergangenheit auf dieses Problem gestoßen. Die Frage war jedoch, ob diese Indexgröße akzeptabel ist und wie sie reduziert werden kann, weil IMH (noob) O mit einem Index größer als meine Daten außer Kontrolle geraten ist - deshalb werde ich die Antwort nicht als akzeptiert markieren. –

+0

Auch etwas, das ich dachte, war es wert, darauf hinzuweisen - führt die ursprüngliche Abfrage von der Frage ohne Offset zurück in 1ms, aber die gleichen Ergebnisse mit Union erhalten kehrt in 50ms. Ich erinnere mich, dass ich das auch getestet habe, als ich den Tisch entwarf, und das war damals auch der Fall - "OR" übertrifft oft "UNION". –

Verwandte Themen