Heim > Datenbank > MySQL-Tutorial > Der Unterschied zwischen MySQL Merge Union Merge sort_union

Der Unterschied zwischen MySQL Merge Union Merge sort_union

伊谢尔伦
Freigeben: 2016-11-21 15:20:24
Original
1464 Leute haben es durchsucht

Nachdem ich die Indexzusammenführungsoptimierung im MYSQL-Handbuch gesehen habe, kamen mir einige Ideen, also habe ich sie wie folgt aufgezeichnet

Erklären wir zunächst den Unterschied zwischen den beiden Methoden:
Beide Da die Methoden denselben Sekundärindex verwenden, ist zu beachten, dass es sich um eine einzelne Tabelle handelt.
Zusammenführungsvereinigung: Wenn Sie oder verwenden, wenn der Sekundärindex alle Schlüsselteile enthält, können Sie den Schlüsselwert oder die ROWID des sortierten Clustered-Index erhalten. Dann reicht eine einfache Vereinigung aus, um Duplikate zu entfernen, keine zusätzliche Sortierung
Quellcode-Schnittstelle quick_ror_union_select-Klasse
merge sort_union: Der Unterschied zu oben besteht darin, dass nicht alle Schlüsselteile des Sekundärindex enthalten sind. Daher müssen Sie zuerst den sortierten Clustered-Index-Schlüsselwert oder die ROWID abrufen, bevor Sie den Cluster sortieren können index Schlüsselwert oder ROWID für Union-Operationen
Quellcode-Schnittstelle quick_index_merge_select
Referenzhandbuch: 9.2.1.4 Optimierung der Indexzusammenführung
Im Allgemeinen, solange MySQL nicht feststellen kann, dass der Primärschlüssel eine gute Sortiermethode ist, zusätzlich Sortiervorgänge sind erforderlich.


Wenn wir ein gewisses Verständnis des Zusammenführungssortierungsalgorithmus haben, können wir erkennen, dass eine solche Verarbeitung notwendig ist.
Wir wissen, dass alle Teilmengen, die zusammengeführt werden müssen, beim Zusammenführen sortiert werden müssen. Ja, das Folgende ist ein Diagramm eines einfachen Zusammenführungsalgorithmus:

Der Unterschied zwischen MySQL Merge Union Merge sort_union

Wenn wir 1 2 5 9 und 3 4 7 8 als Primärschlüssel betrachten, müssen sie sortiert werden . Schließen Sie die endgültige Zusammenführung ab. Natürlich können auch andere Sortiermethoden verwendet werden, sofern die Sortierung abgeschlossen ist Bei Datenstrukturen sollte man wissen, dass es auch auf externen Festplatten gut sortiert ist.

Um dies zu verstehen, müssen wir die Anordnung des kombinierten Index im INNODB B-Baumseitenblock verstehen:
Zum Beispiel: seq int, id1 int, id2 int seq ist der Primärschlüssel, ID1, DI2 ist ein Kombinations-B-Index
, dann fügen wir den Wert


ein. Offensichtlich sind die Blattknoten des kombinierten Index in der folgenden Reihenfolge angeordnet:
values(1,1,2)
values(2,1,3)
values(3,1,2)
Nach dem Login kopieren



, das heißt, zuerst nach ID1 sortieren, dann nach ID2 sortieren und schließlich nach Primärschlüsselsequenz sortieren
1       2       3
id1:1  id1:1  id1:1
id2:2  id2:2  id2:3
seq:1  seq:3  seq:2
Nach dem Login kopieren
Dann können Sie sehen, dass die Reihenfolge des endgültigen Primärschlüssels 1 ist 3 2, was offensichtlich nicht in Ordnung ist. Eine solche

-Ergebnismenge kann nicht als zusammengeführte Ergebnismenge verwendet werden. Daher müssen wir sortieren.

Dann zeigen wir den Unterschied zwischen den beiden Ausführungsplänen
Skript:



create table testmer
(seq int,id1 int,id2 int,id3 int,id4 int,primary key(seq),key(id1,id2),key(id3,id4));
insert into testmer values(1,1,2,4,4);
insert into testmer values(2,1,3,4,5);
insert into testmer values(3,1,2,4,4);
insert into testmer values(4,2,4,5,6);
insert into testmer values(5,2,6,5,8);
insert into testmer values(6,2,10,5,3);
insert into testmer values(7,4,5,8,10);
insert into testmer values(8,0,1,3,4);
Nach dem Login kopieren
Natürlich schauen wir uns nur key(id1,id2) an. Hier muss sortiert werden, da die Anordnung wie folgt lautet:
mysql> select * from testmer;
+-----+------+------+------+------+
| seq | id1  | id2  | id3  | id4  |
+-----+------+------+------+------+
|   1 |    1 |    2 |    4 |    4 |
|   2 |    1 |    3 |    4 |    5 |
|   3 |    1 |    2 |    4 |    4 |
|   4 |    2 |    4 |    5 |    6 |
|   5 |    2 |    6 |    5 |    8 |
|   6 |    2 |   10 |    5 |    3 |
|   7 |    4 |    5 |    8 |   10 |
|   8 |    0 |    1 |    3 |    4 |
+-----+------+------+------+------+
Nach dem Login kopieren
1 2 3
Using sort_union:
mysql> explain  select * from testmer force index(id1,id3) where id1=1 or id3=4;
+----+-------------+---------+------------+-------------+---------------+---------+---------+------+------+----------+----------------------------------------+
| id | select_type | table   | partitions | type        | possible_keys | key     | key_len | ref  | rows | filtered | Extra                                  |
+----+-------------+---------+------------+-------------+---------------+---------+---------+------+------+----------+----------------------------------------+
|  1 | SIMPLE      | testmer | NULL       | index_merge | id1,id3       | id1,id3 | 5,5     | NULL |    6 |   100.00 | Using sort_union(id1,id3); Using where |
+----+-------------+---------+------------+-------------+---------------+---------+---------+------+------+----------+----------------------------------------+
1 row in set, 1 warning (5.07 sec)
Nach dem Login kopieren
id1:1 id1:1 id1:1

id2:2 id2:2 id2:3
seq:1 seq:3 seq: 2

Wenn wir den Sekundärindex KEY_PART mit allen nehmen



Natürlich ist hier keine Sortierung erforderlich. Wir sehen id1=1 und id2 =2(id3=4 und id4=1 Dasselbe)

ist wie folgt angeordnet:
mysql> explain  select * from testmer force index(id1,id3) where id1=1 and id2=2 or id3=4 and id4=1;
+----+-------------+---------+------------+-------------+---------------+---------+---------+------+------+----------+-----------------------------------+
| id | select_type | table   | partitions | type        | possible_keys | key     | key_len | ref  | rows | filtered | Extra                             |
+----+-------------+---------+------------+-------------+---------------+---------+---------+------+------+----------+-----------------------------------+
|  1 | SIMPLE      | testmer | NULL       | index_merge | id1,id3       | id1,id3 | 10,10   | NULL |    2 |   100.00 | Using union(id1,id3); Using where |
+----+-------------+---------+------------+-------------+---------------+---------+---------+------+------+----------+-----------------------------------+
Nach dem Login kopieren



Mit anderen Worten, wenn KEY_PART vollständig enthält, wird der Primärschlüssel auf natürliche Weise sortiert ,

1         2      
id1:1   id1:1   
id2:2   id2:2 
seq:1  seq:3
Nach dem Login kopieren
Eigentlich arbeite ich in einer DEBUG-Umgebung. Ja, der Haltepunkt wird bei Unique::unique_add




erreicht, wenn „select * from testmer force index(id1,id3.)“ ausgeführt wird ) wobei id1=1 und id2=1 oder id3=4 und id4 =1;

Unique::unique_add wird nicht ausgelöst, d. h. es wird kein Sortiervorgang durchgeführt.
(gdb) info b
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x0000000000ebd333 in main(int, char**) at /root/mysql5.7.14/percona-server-5.7.14-7/sql/main.cc:25
        breakpoint already hit 1 time
6       breakpoint     keep y   0x000000000145de13 in Unique::unique_add(void*) at /root/mysql5.7.14/percona-server-5.7.14-7/sql/uniques.h:52
        breakpoint already hit 2 times
Nach dem Login kopieren

Abschließend erklären wir die Sortierschnittstelle merge_sort des Quellcodes
QUICK_INDEX_MERGE_SELECT::read_keys_and_merge()
Aufruf
Unique::unique_add
(Verwenden Sie ausgeglichene Binärbäume, ausgeglichene Binärbäume sind keine rot-schwarzen Bäume. Differenzreferenz:
http://blog.itpub.net/7728585/viewspace-2127419/
)

Das Folgende ist der Kommentar zum Quellcode read_keys_and_merge() :



Das Folgende sind die Stapelinformationen, wenn ich GDB verwende:

/*
  Perform key scans for all used indexes (except CPK), get rowids and merge 
  them into an ordered non-recurrent sequence of rowids.
  
  The merge/duplicate removal is performed using Unique class. We put all
  rowids into Unique, get the sorted sequence and destroy the Unique.
  
  If table has a clustered primary key that covers all rows (TRUE for bdb
  and innodb currently) and one of the index_merge scans is a scan on PK,
  then rows that will be retrieved by PK scan are not put into Unique and 
  primary key scan is not performed here, it is performed later separately.
  RETURN
    0     OK
    other error
*/
Nach dem Login kopieren


Anbei sind die beiden Methoden zum Aufrufen der Funktionsschnittstelle:

merge sort_union:
(gdb) bt
#0  tree_insert (tree=0x7fffd801c768, key=0x7fffd801ada0, key_size=0, custom_arg=0x7fffd80103d0) at /root/mysql5.7.14/percona-server-5.7.14-7/mysys/tree.c:207
#1  0x000000000145df19 in Unique::unique_add (this=0x7fffd801c260, ptr=0x7fffd801ada0) at /root/mysql5.7.14/percona-server-5.7.14-7/sql/uniques.h:56
#2  0x000000000178e6a8 in QUICK_INDEX_MERGE_SELECT::read_keys_and_merge (this=0x7fffd89083f0) at /root/mysql5.7.14/percona-server-5.7.14-7/sql/opt_range.cc:10700
#3  0x0000000001778c73 in QUICK_INDEX_MERGE_SELECT::reset (this=0x7fffd89083f0) at /root/mysql5.7.14/percona-server-5.7.14-7/sql/opt_range.cc:1601
#4  0x000000000155e529 in join_init_read_record (tab=0x7fffd8906e20) at /root/mysql5.7.14/percona-server-5.7.14-7/sql/sql_executor.cc:2471
#5  0x000000000155b6a1 in sub_select (join=0x7fffd8905b08, qep_tab=0x7fffd8906e20, end_of_records=false)
    at /root/mysql5.7.14/percona-server-5.7.14-7/sql/sql_executor.cc:1271
#6  0x000000000155b026 in do_select (join=0x7fffd8905b08) at /root/mysql5.7.14/percona-server-5.7.14-7/sql/sql_executor.cc:944
#7  0x0000000001558efc in JOIN::exec (this=0x7fffd8905b08) at /root/mysql5.7.14/percona-server-5.7.14-7/sql/sql_executor.cc:199
#8  0x00000000015f91c6 in handle_query (thd=0x7fffd8000df0, lex=0x7fffd80033d0, result=0x7fffd8007a60, added_options=0, removed_options=0)
    at /root/mysql5.7.14/percona-server-5.7.14-7/sql/sql_select.cc:184
#9  0x00000000015ac025 in execute_sqlcom_select (thd=0x7fffd8000df0, all_tables=0x7fffd8006e98) at /root/mysql5.7.14/percona-server-5.7.14-7/sql/sql_parse.cc:5391
#10 0x00000000015a4640 in mysql_execute_command (thd=0x7fffd8000df0, first_level=true) at /root/mysql5.7.14/percona-server-5.7.14-7/sql/sql_parse.cc:2889
#11 0x00000000015acff6 in mysql_parse (thd=0x7fffd8000df0, parser_state=0x7ffff0fd6600) at /root/mysql5.7.14/percona-server-5.7.14-7/sql/sql_parse.cc:5836
#12 0x00000000015a0eb5 in dispatch_command (thd=0x7fffd8000df0, com_data=0x7ffff0fd6d70, command=COM_QUERY)
    at /root/mysql5.7.14/percona-server-5.7.14-7/sql/sql_parse.cc:1447
#13 0x000000000159fce6 in do_command (thd=0x7fffd8000df0) at /root/mysql5.7.14/percona-server-5.7.14-7/sql/sql_parse.cc:1010
#14 0x00000000016e1c08 in handle_connection (arg=0x3c1c880) at /root/mysql5.7.14/percona-server-5.7.14-7/sql/conn_handler/connection_handler_per_thread.cc:312
#15 0x0000000001d71ed0 in pfs_spawn_thread (arg=0x3bec1b0) at /root/mysql5.7.14/percona-server-5.7.14-7/storage/perfschema/pfs.cc:2188
#16 0x0000003ca62079d1 in start_thread () from /lib64/libpthread.so.0
#17 0x0000003ca5ee8b6d in clone () from /lib64/libc.so.6
Nach dem Login kopieren




merge union:

T@3: | | | | | | | | | | >QUICK_INDEX_MERGE_SELECT::QUICK_INDEX_MERGE_SELECT
T@3: | | | | | | | | | | <QUICK_INDEX_MERGE_SELECT::QUICK_INDEX_MERGE_SELECT 1589
T@3: | | | | | | | | | | >QUICK_INDEX_MERGE_SELECT::init
T@3: | | | | | | | | | | <QUICK_INDEX_MERGE_SELECT::init 1595
T@3: | | | | | | | | >QUICK_INDEX_MERGE_SELECT::reset
T@3: | | | | | | | | | >QUICK_INDEX_MERGE_SELECT::read_keys_and_merge
T@3: | | | | | | | | | <QUICK_INDEX_MERGE_SELECT::read_keys_and_merge 10716
T@3: | | | | | | | | <QUICK_INDEX_MERGE_SELECT::reset 1602
T@3: | | | | | | | | >QUICK_INDEX_MERGE_SELECT::get_next
T@3: | | | | | | | | <QUICK_INDEX_MERGE_SELECT::get_next 10753
T@3: | | | | | | | | >QUICK_INDEX_MERGE_SELECT::get_next
T@3: | | | | | | | | <QUICK_INDEX_MERGE_SELECT::get_next 10753
T@3: | | | | | | | | >QUICK_INDEX_MERGE_SELECT::get_next
T@3: | | | | | | | | <QUICK_INDEX_MERGE_SELECT::get_next 10753
T@3: | | | | | | | | >QUICK_INDEX_MERGE_SELECT::get_next
T@3: | | | | | | | | <QUICK_INDEX_MERGE_SELECT::get_next 10753
T@3: | | | | | | | >QUICK_INDEX_MERGE_SELECT::~QUICK_INDEX_MERGE_SELECT
T@3: | | | | | | | <QUICK_INDEX_MERGE_SELECT::~QUICK_INDEX_MERGE_SELECT 1635
Nach dem Login kopieren



Sie können den Aufrufpfad sehen und die Aufrufsituation im Quellcode überprüfen Ich möchte nur beweisen, dass die Sortierung tatsächlich durchgeführt wurde, und dann sehen, welche Sortiermethode verwendet wird.

Dieser Artikel gibt nur meine persönliche Meinung wieder, bitte warnen Sie mich. Danke!
T@3: | | | | | | | | | | >QUICK_ROR_UNION_SELECT::init
T@3: | | | | | | | | | | <QUICK_ROR_UNION_SELECT::init 1942
T@3: | | | | | | | | >QUICK_ROR_UNION_SELECT::reset
T@3: | | | | | | | | <QUICK_ROR_UNION_SELECT::reset 2004
T@3: | | | | | | | | >QUICK_ROR_UNION_SELECT::get_next
T@3: | | | | | | | | <QUICK_ROR_UNION_SELECT::get_next 10948
T@3: | | | | | | | | >QUICK_ROR_UNION_SELECT::get_next
T@3: | | | | | | | | <QUICK_ROR_UNION_SELECT::get_next 10948
T@3: | | | | | | | | >QUICK_ROR_UNION_SELECT::get_next
T@3: | | | | | | | | <QUICK_ROR_UNION_SELECT::get_next 10913
T@3: | | | | | | | >QUICK_ROR_UNION_SELECT::~QUICK_ROR_UNION_SELECT
T@3: | | | | | | | <QUICK_ROR_UNION_SELECT::~QUICK_ROR_UNION_SELECT 2021
Nach dem Login kopieren


Das Obige sind die verschiedenen Inhalte von mysql merge union merge sort_union. Weitere verwandte Inhalte finden Sie auf der chinesischen PHP-Website (m.sbmmt.com).


Verwandte Etiketten:
Quelle:php.cn
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage