2016-07-05 18 views
0

Ich habe Ansicht von UNION ALL-Klausel von etwa 10 Tabellen erstellt und einige Suchanfragen nach Datumsbereich darauf anwenden möchten. Aber wenn die Anzahl der Datensätze zunimmt, dauert es länger, die Abfrage auszuführen. Im Moment hat die Ansicht 2 Milliarden Zeilen.Ist es möglich, eine Ansicht wie eine Tabelle in MySQL zu partitionieren?

Tabellenstruktur ist wie:

CREATE TABLE IF NOT EXISTS `tbl_queue_stats_0716` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `server_id` int(11) NOT NULL, 
    `uniqueid` varchar(100) DEFAULT NULL, 
    `queue_datetime` datetime NOT NULL, 
    `queue_timestamp` varchar(100) NULL, 
    `qname_id` int(11) NOT NULL, 
    `qagent_id` int(11) NOT NULL, 
    `qevent_id` int(11) NOT NULL, 
    `info1` varchar(100) DEFAULT NULL, 
    `info2` varchar(100) DEFAULT NULL, 
    `info3` varchar(100) DEFAULT NULL, 
    `info4` varchar(100) DEFAULT NULL, 
    `info5` varchar(100) DEFAULT NULL, 
    PRIMARY KEY (`id`) 
); 

Tabellen auf monatlicher Basis erstellt werden, so kann es Tabellen wie tbl_queue_stats_0616, tbl_queue_stats_0516, tbl_queue_stats_0416 ...

Und ich will Suchanfrage auf mehrere anwenden Tabellen, wenn der Zeitraum für die Suche nach 2 oder mehr Monaten erforderlich ist.

Suchabfrage ist wie folgt aussehen:

select server_id,server_name,queue_id,queue_name,qevent_id,event, 
     count(id) as cnt,sum(info1) as info1, sum(info2) as info2, 
     sum(info3) as info3, sum(info4) as info4, sum(info5) as info5, 
     max(cast(info2 AS SIGNED)) as max_info2, 
     max(cast(info3 AS SIGNED)) as max_info3 
    from 
     (SELECT a.server_id as server_id,e.server_name as server_name, 
       a.id,a.`queue_datetime`, b.agent, a.qname_id as queue_id , 
       c.queue as queue_name,d.event,a.qevent_id,a.info1,a.info2, 
       a.info3,a.info4,a.info5 
      FROM view_queue_stats a,tbl_qagent b, tbl_qname c, tbl_qevent d, 
       tbl_server e 
      WHERE a.qagent_id=b.id 
       AND a.qname_id=c.id 
       AND a.qevent_id=d.id 
       AND a.server_id=e.id 
       AND DATE(a.queue_datetime) between '" . $start_date . 
              "' AND '" . $end_date . "' 
       AND a.server_id IN ($server_name) 
    )as total 
    GROUP BY qevent_id,queue_id,server_id 
    ORDER BY length(server_name), server_name,queue_id,qevent_id. 

Ich denke Durchsuchung partitionierten Sicht kann meine Abfrage schneller ausgeführt. Um dies zu erreichen, habe ich partitionsbezogene Parameter angewendet, um die Ansicht zu erstellen, aber nicht erfolgreich.

Darunter ist die Ausgabe von SHOW CREATE VIEW view_queue_stats;

CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER 
     VIEW `view_queue_stats` 
     AS select `tbl_queue_stats_0116`.`id` AS `id`, 
     `tbl_queue_stats_0116`.`server_id` AS `server_id`, 
     `tbl_queue_stats_0116`.`uniqueid` AS `uniqueid`, 
     `tbl_queue_stats_0116`.`queue_datetime` AS `queue_datetime`, 
     `tbl_queue_stats_0116`.`queue_timestamp` AS `queue_timestamp`, 
     `tbl_queue_stats_0116`.`qname_id` AS `qname_id`, 
     `tbl_queue_stats_0116`.`qagent_id` AS `qagent_id`, 
     `tbl_queue_stats_0116`.`qevent_id` AS `qevent_id`, 
     `tbl_queue_stats_0116`.`info1` AS `info1`, 
     `tbl_queue_stats_0116`.`info2` AS `info2`, 
     `tbl_queue_stats_0116`.`info3` AS `info3`, 
     `tbl_queue_stats_0116`.`info4` AS `info4`, 
     `tbl_queue_stats_0116`.`info5` AS `info5` 
    from `tbl_queue_stats_0116` 
    union all 
select `tbl_queue_stats_0216`.`id` AS `id`, 
     `tbl_queue_stats_0216`.`server_id` AS `server_id`, 
     `tbl_queue_stats_0216`.`uniqueid` AS `uniqueid`, 
     `tbl_queue_stats_0216`.`queue_datetime` AS `queue_datetime`, 
     `tbl_queue_stats_0216`.`queue_timestamp` AS `queue_timestamp`, 
     `tbl_queue_stats_0216`.`qname_id` AS `qname_id`, 
     `tbl_queue_stats_0216`.`qagent_id` AS `qagent_id`, 
     `tbl_queue_stats_0216`.`qevent_id` AS `qevent_id`, 
     `tbl_queue_stats_0216`.`info1` AS `info1`, 
     `tbl_queue_stats_0216`.`info2` AS `info2`, 
     `tbl_queue_stats_0216`.`info3` AS `info3`, 
     `tbl_queue_stats_0216`.`info4` AS `info4`, 
     `tbl_queue_stats_0216`.`info5` AS `info5` 
    from `tbl_queue_stats_0216` 
    union all 
    ... 

| utf8     | utf8_general_ci  | 

Also, gibt es eine Möglichkeit, eine Ansicht zu partitionieren?

+0

Welche ENGINE sind die Tabellen? –

+0

Warum haben Sie die Daten in Monaten "manuell" partitioniert? Performance (die Sie wahrscheinlich nicht bekommen haben)? Bequemlichkeit (über die Sie sich beschweren)? Andere? –

+0

ENGINE ist InnoDB für alle Tabellen. Ich habe alle Tabellen in Monat unterteilt, weil es Millionen von Datensätzen in einer einzigen Tabelle gibt. Das Erstellen einer einzelnen Tabelle für alle Daten macht die Tabelle erschöpfend, denke ich. Gibt es dafür eine Alternative? – Dhruten

Antwort

0

Überprüfen Sie den Link unten .Das gegeben können Sie

http://dev.mysql.com/doc/refman/5.5/en/partitioning.html

+0

Tabelle Partitionierung ist sehr gut erklärt, aber nichts für mein Problem nützlich gefunden. – Dhruten

+0

Ja, Partitionierung ist selten eine Lösung. Bitte geben Sie 'SHOW CREATE TABLE' und die Abfrage an; dann kann ich etwas konstruktiveres sagen. –

+0

@RickJames Bitte überprüfen Sie die bearbeitete Frage. – Dhruten

1

Wollen Sie eine Milliarde server_ids helfen haben? Vielleicht könnten Sie einen kleineren Int verwenden, wie MEDIUMINT UNSIGNED, der 3 Byte (statt 4) und ein Limit von 16M ist. Dito für andere IDs. (Kleiner -> mehr cachefähig -> weniger I/O -> schneller)

Ist queue_timestamp ein Zeitstempel? Wenn ja, warum VARCHAR?

cast(info2 AS SIGNED) - Sie wäre besser dran, die Datenbereinigung vor es eingesetzt wird, und dann einen entsprechenden Datentyp mit (INT?).

wichtig: Verstecken Sie keine Spalten in Funktionen (DATE(a.queue_datetime)), es verhindert die Verwendung von Indizes; siehe unten.

Sind die meisten Felder wirklich optional? Wenn nicht, sagen Sie NOT NULL anstelle von NULL.

wichtig: Zurück zur Frage ... UNION ALL von 10 Tabellen zu einer PARTITIONed Tabelle ähnlich durchführen, wo keine „Partition Pruning“ auftreten kann. Aber die UNION ist wahrscheinlich schlimmer, weil es scheint, die temporäre Tabelle zu generieren, die alle Daten enthält, und dann zu filtern. Bitte geben Sie EXPLAIN SELECT ... für die Abfrage an. (Dies sollte bestätigen oder leugnen diese Annahme. Es könnte einen großen Unterschied machen.)

wichtig:INDEX(server_id, queue_datetime) ist wahrscheinlich, um die Leistung zu helfen.

Also, die Frage ist jetzt, ob "Beschneiden" auftreten kann. Der wahrscheinlichste Fall ist, wenn query_datetime das Ergebnis auf wenige Partitionen beschränken würde.Basieren die Tabellen auf query_datetime? Sind die SELECTs normalerweise auf eine oder zwei Tabellen beschränkt?

die richtigen Antworten auf die oben gegeben, und die Änderungen vorgeschlagen gegeben, dann aus einem VIEW auf diese Veränderung wesentlich helfen:

PARTITION BY RANGE(TO_DAYS(query_datetime)) ... 

Aber, wie sich herausstellt, Partitionierung nicht wirklich notwendig ist. Die oben vorgeschlagene INDEX (zusammen mit der Änderung der WHERE) wird genauso gut auf einer einzigen Tabelle tun.

Aber ... Noch ein paar Fragen. Sie erwähnten eine SELECT; Gibt es andere? Das Korrigieren der Abfrage/des Schemas für eine Abfrage kann anderen Abfragen möglicherweise nicht helfen. Löschen Sie "alte" Tabellen/Partitionen? Wenn das so ist, kann das gut helfen.

Beantworten Sie diese Probleme, dann können wir eine Korrektur mitten im Kurs vornehmen.