2016-05-19 15 views
1

Ich versuche Vorteile der Partitionierung in Mysql zu testenWarum MySQL-Partitionierung keine Wirkung in meinem Fall hat

Ich habe zwei Tabellen: eine partitionierten andere nicht.

Jede Tabelle enthält 10M Datensätze.

Ich möchte schnelle Abfrage von "user_to_id" Spalte.

partitionierten Tabelle (1024 Teile):

CREATE TABLE `neworder10M_part_byuser` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `site_from_id` int(11) NOT NULL, 
    `site_to_id` int(11) NOT NULL, 
    `user_from_id` int(11) NOT NULL, 
    `user_to_id` int(11) NOT NULL, 
    `created` datetime NOT NULL, 
    PRIMARY KEY (`id`,`user_to_id`), 
    KEY `composite_cover` (`user_to_id`,`user_from_id`,`site_from_id`,`site_to_id`,`created`) 
) ENGINE=InnoDB 
/*!50100 PARTITION BY HASH (user_to_id) 
PARTITIONS 1024 */ | 

Tabelle mit Clustered-Schlüssel (nicht partitioniert):

CREATE TABLE `neworder_10M` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `site_from_id` int(11) NOT NULL, 
    `site_to_id` int(11) NOT NULL, 
    `user_from_id` int(11) NOT NULL, 
    `user_to_id` int(11) NOT NULL, 
    `created` datetime NOT NULL, 
    PRIMARY KEY (`user_to_id`,`id`), 
    UNIQUE KEY `id_UQ` (`id`) 
) ENGINE=InnoDB; 

wenn ich Benchmark beiden Tabellen mit Python-Skript für 1000 reqs:

for i in xrange(1,REQS): 
    user_id = random.randint(1,10000); 
    cursor.execute("select * from neworder10M_part_byuser where user_to_id=%s;" % (user_id)) 

Partitionierte Tabelle: 22 rps Nicht partitioniert: 22.7 rps

Warum hat die partitionierte Tabelle keine Geschwindigkeitsvorteile? Da erwarte ich kleinere Daten - schnellere Abfrage.

Und erklären zeigt auch, dass die Partition:

mysql> explain select * from neworder10M_part_byuser where user_to_id=6867; 
+----+-------------+-------------------------+------------+------+-----------------+-----------------+---------+-------+------+----------+-------------+ 
| id | select_type | table     | partitions | type | possible_keys | key    | key_len | ref | rows | filtered | Extra  | 
+----+-------------+-------------------------+------------+------+-----------------+-----------------+---------+-------+------+----------+-------------+ 
| 1 | SIMPLE  | neworder10M_part_byuser | p723  | ref | composite_cover | composite_cover | 4  | const | 1009 | 100.00 | Using index | 
+----+-------------+-------------------------+------------+------+-----------------+-----------------+---------+-------+------+----------+-------------+ 

aber ich reale Geschwindigkeit nicht in der Realität verbessern sehen .... was ich falsch mache?

Tabellen füllen Code:

def send_orders(cur,users=10000,orders=10000000): 
    for i in xrange(1,orders+1): //10000000 rows here 
     print i 
     from_user = random.randint(1,users) 
     to_user = random.randint(1,users) 
     from_site = random.randint(1,10000) 
     to_site = random.randint(1,10000) 
     cur.execute("INSERT INTO neworder (site_from_id, site_to_id,user_from_id, user_to_id,created) VALUES ('%d','%d','%d','%d',NOW());" % (from_user,to_user,from_site,to_site)) 

MySQL-Version: Ver 14.14 Distrib 5.7.12, für Linux (x86_64). Festplatte ist SSD.

Antwort

0

Wir würden nicht erwarten, dass die SELECT-Anweisungen einen großen Leistungsunterschied aufweisen, da die Abfragen einen Indexbereichscan verwenden und die Abfrage der partitionierten Tabelle Partitionen beschneidet.

Ohne die Partition Bereinigung würden wir erwarten langsamer Leistung mit einem SELECT gegen die partitionierte Tabelle. Da wären das 1024 Indizes, die gegen einen Index überprüft werden müssen.

Die Idee, dass Partitionierung die Abfrageleistung verbessert, ist ein Trugschluss.

+0

"Wir würden nicht erwarten, dass es bei den SELECT-Anweisungen zu großen Leistungsunterschieden kommt." Warum? Wie ich durch den Partitionsschlüssel verstehe, ist es möglich, die Partition pXXX für O (1) mal zu bestimmen und dann nur eine bestimmte Partitionsübereinstimmung schneller zu scannen, da ihr Index 10K Zeilen vs. 10M Zeilen von Nicht-Partition-Volldatentabellenindex enthält. Warum sollte der Zeit-Scan-Index für 10K-Zeilen dem Index-Scan für 10M-Zeilen entsprechen? – Evg

+0

Weil es keinen * vollständigen * Scan jedes Indexeintrags macht. Der Index ist so organisiert, dass die Speicher-Engine sehr schnell die Blöcke eingrenzen kann, die die gesuchten Einträge enthalten könnten. Mit dem Index gibt es große Schwaden von Blöcken, in denen die Einträge nicht sein können. So funktionieren Indizes. Bei der Lokalisierung der Einträge spielt es keine Rolle, ob 10.000 Blöcke oder 10.000.000 Blöcke nicht untersucht werden müssen. Aus diesem Grund ist die Leistung gleich. – spencer7593

+0

"Es spielt keine Rolle, ob es 10.000 Blöcke oder 10.000.000 Blöcke gibt, die nicht untersucht werden müssen. Deshalb ist die Leistung die gleiche." I Mysql "Ich denke, das ist eine falsche Aussage. Index verwenden b + Bäume. So Zeitprotokoll (N) Ich teste nur Tabelle für 100K Zeilen und bekomme 1215 rps vs 20 rps auf 10M Zeilen Tabelle.So suche in Partition mit 10K Zeilen shiuldd viel schneller als 100K, und viel mehr dann mit 10M – Evg

0

(Dies ist sowohl eine Antwort auf die Frage und eine Widerlegung einige der Kommentare.)

Wenn Ihre WHERE Klausel Partition Pruning verursachen kann passieren, dann kann es helfen, einen Composite-Index effizienter zu machen. Daher kein Vorteil gegenüber einer nicht partitionierten Tabelle, da Sie einen besseren Index wählen können.

Stellen Sie sich das Beschneiden der Partition vor, wenn Sie die BTree-Tiefe um 1 Stufe verringern. Aber dann musst du den Schnitt machen. Ergebnis: praktisch die gleichen Kosten. Dies ist meine Antwort auf die Frage nach "Bereichsscan auf 10M Zeilen unpartitioniert vs 10K Zeilen in einer Partition". (@ spencer7593's Antworten sind auch gut.)

Es gibt nur 4 Anwendungsfälle, die ich gefunden habe, wo PARTITIONing die Leistung verbessert.Es gibt my blog.

BY RANGE ist die einzige nützliche Partitionierungsmethode. BY HASH, die Sie verwenden, scheint völlig nutzlos zu sein. Insbesondere, wenn Sie einen Bereichsscan auf dem 'Partitionsschlüssel' durchführen, wird er notwendigerweise alle Partitionen scannen - kein 'Beschneiden' ist möglich.

Es ist normalerweise ineffizient, den Partitionsschlüssel zuerst in einen beliebigen Schlüssel zu setzen.

UNIQUE KEY id_UQ (id) - machen Sie das eine einfache INDEX für Ihre Nicht-Partition Test; es wird effizienter sein. Und es wird ausreichen, um AUTO_INCREMENT zu behandeln.

(Oops, @ spencer7593 sagte bereits einige dieser Dinge, und deutete auf meinen Blog. Danke. Ich habe es geschrieben, weil ich wiederhole mich in den Foren müde.)

Ihre spezielle Abfrage (SELECT ... WHERE user_to_id = constant) ist ein guter Weg, um zu demonstrieren, wie nutzlos PARTITIONing (jeder Art) ist. Ist das deine echte Frage? Sie haben möglicherweise einige andere Abfragen, die von der Partitionierung profitieren könnten. Lass uns sie sehen.

"50x schneller auf kleinerer Tabelle" - Caching? Passt die kleinere Tabelle in den buffer_pool, aber die größere nicht? I/O ist der größte Leistungsfaktor.

Wenn WHERE user_to_id = constant immer in Ihren Abfragen vorhanden ist, dann haben Sie user_to_id als die erste Spalte in jedem Index (außer INDEX(id)) in einer nicht partitionierten Tabelle. Stellen Sie sich das als "Beschneiden" vor.

Verwandte Themen