2017-07-07 6 views
2

Ich habe eine Tabelle Beiträge mit den folgenden Spalten:
start_at, sun, mon, tue, wen, thu, fri, satIndexing eine MYSQL Tabelle mit vielen Spalten

start_at ist der Datumstypen, die andere - Tinyint.

Ich mache eine Abfrage die folgende Art und Weise:

SELECT * FROM posts WHERE start_at >= '2017-02-01' AND mon = 1 

, das nach dem zweiten und ich richtigem Wochentag dynamisch festgelegt.

Was ist der beste Weg, diese Tabelle zu indizieren? Benötige ich einen zusammengesetzten Index für jeden Tag der Woche zu machen, zum Beispiel:

CREATE INDEX mon_index ON posts(start_at,mon); 
CREATE INDEX sun_index ON posts(start_at,sun); 

Wenn ich erstelle 7 Indizes für jeden Tag der Woche, ich glaube, INSERT und UPDATE wirklich langsam sein werden.

AKTUALISIERT: Ich brauche Spalte für jeden Wochentag, weil ein Benutzer legt fest, an welchen Tagen Post veröffentlicht wird. Es kann ein paar Tage zur selben Zeit sein.

+0

Warum brauchen Sie diesen Tisch? Es scheint mir sinnvoller zu sein, eine einzige Datumsspalte zu haben. In Bezug auf den Index hängt es davon ab, wie Sie die Tabelle verwenden möchten. –

+0

mehr als eins von Sonne, Mon, etc. kann 1 auf dem gleichen Datensatz sein? – etsa

+0

https://dba.stackexchange.com/ könnte ein besserer Ort sein, um das zu fragen? –

Antwort

3

Ihr Schema wurde seltsam gestaltet. Ihr aktuelles Setup mag für eine einfache Berichterstellung sorgen, aber Sie sind richtig. Die Indexierung, wie Sie es vorgeschlagen haben, führt zu einer schrecklichen Performance von insert und update.

Mein Vorschlag wäre, diese Tabelle umzuformen. Anstatt Ihrer aktuellen Einstellung würde ich vorschlagen, dass Sie die Tabelle posts ändern, um die Spalten zu haben (start_at, day). In diesem Design kann der Tag von Sonntag bis Samstag sein und Sie benötigen nur einen Index (start_at, day).

Wenn Sie wirklich das aktuelle Format zum Lesen/Melden von Gründen benötigen (ich würde Sie nicht tadeln), könnten Sie immer eine Ansicht einrichten, die die Daten auf diese Weise dreht.


All das gesagt wird, nicht jedes Feld, das Sie auf Bedürfnisse qualifizieren in einem Index zu sein. Meine Schätzung ist, dass die große Mehrheit der Zeilen Ihrer Tabelle einfach nach dem Datum gefiltert werden kann. Die wenigen, die übrig sind wahrscheinlich nicht müssen für dezente Leseleistung indiziert werden.


In einer anderen Art, warum auch den Tag speichern? Dies kann basierend auf dem Datum berechnet werden.

0

Wie ein anderer sagte, möglicherweise sollte es ausreichen, nur für start_at zu indizieren.

Wenn Sie den Index nach dem Veröffentlichungstag untersuchen möchten (insbesondere wenn Ihre Tabelle viele Felder enthält und Sie nur Felder start_at und den Tag der Veröffentlichung auflisten möchten), könnten Sie eine Tabelle wie folgt erstellen:

CREATE TABLE XX (start_at ..., which_day tinyint UNSIGNED); 

und ein Index wie dieser

CREATE INDEX XX_IX01 (start_at, which_day); 

wo which_day sein kann, eine Art Codierung mit:

0 = kein Tag 2^0 = Sonne 2^1 = Mon 2^2 = .. ... 2^6 = sat

Also, zum Beispiel, wenn Mon und Sat 1 sind, sollte der Wert 2^1 + 2^6 = 2 + 64 = 66 sein.

Wenn möglich, SELECT * und schreiben Sie das Feld, das Sie brauchen.

Verwenden Sie EXPLAIN, um zu überprüfen, wie db engine Ihren Index/Tabellen verwendet.

könnte Dieser Link nützlich sein: How can I index these queries?

Beispieldaten:

CREATE table et1 (start_at DATE, which_day tinyint UNSIGNED); 
CREATE INDEX ET1_IX1 ON et1(start_at, which_day); 

INSERT INTO et1 VALUES ('20170701', 132); 
INSERT INTO et1 VALUES ('20170702', 3); 
INSERT INTO et1 VALUES ('20170704', 5); 
INSERT INTO et1 VALUES ('20170630', 2); 


SELECT start_at, which_day, which_day & 128 AS X FROM et1; 
SELECT start_at, which_day, which_day & 128 AS X FROM et1 WHERE start_at>'20170630' AND which_day & 128 =128; 
EXPLAIN SELECT * FROM et1 WHERE start_at>'20170630' AND which_day & 128 =128; 

DROP table et1; 
+0

Ich brauche Spalte für jeden Wochentag, weil ein Benutzer setzt an welchen Tagen Post veröffentlicht wird. Es kann ein paar Tage zur selben Zeit sein. –

+0

@StasCoder Eigentlich sollten Sie in einem solchen Szenario mehr Zeilen hinzufügen, nicht mehr Spalten. – FMashiro

0

Sie sind über Ihr Datenbankschema zu verkomplizieren, gibt es keine Notwendigkeit, all diese Spalten hinzufügen, noch eine Tonne von Indizes zu erstellen .

Sie können Ihren Beitrag Tisch vereinfachen:

id | title | (...) | start_at 

können Sie dann diese Abfrage ersetzen:

SELECT * FROM posts WHERE start_at >= '2017-02-01' AND mon = 1 

und stattdessen die DAYOFWEEK Funktion:

SELECT * FROM posts WHERE start_at >= '2017-02-01' AND DAYOFWEEK(start_at) = 2 

(1 = Sonntag, 2 = Montag, ..., 7 = Samstag).

Sie können dann einen einzelnen Index für die start_at Spalte beibehalten.

+0

Bitte lesen Sie das Update auf die Frage –

Verwandte Themen