4
die "The PERCONA_TOOLKIT_BRANCH environment variable is not set.\n"
5
unless $ENV{PERCONA_TOOLKIT_BRANCH} && -d $ENV{PERCONA_TOOLKIT_BRANCH};
6
unshift @INC, "$ENV{PERCONA_TOOLKIT_BRANCH}/lib";
10
use warnings FATAL => 'all';
11
use English qw(-no_match_vars);
12
use Test::More tests => 60;
15
require "$trunk/bin/pt-visual-explain";
17
my $e = new ExplainTree;
21
is_deeply( $t, undef, 'No valid input' );
23
$t = $e->parse( load_file("t/pt-visual-explain/samples/fulltext.sql") );
24
## Please see file perltidy.ERR
27
{ type => 'Filter with WHERE',
31
{ type => 'Bookmark lookup',
33
{ type => 'Fulltext scan',
53
$t = $e->parse( load_file("t/pt-visual-explain/samples/impossible_where.sql") );
56
{ type => 'IMPOSSIBLE',
59
warning => 'Impossible WHERE noticed after reading const tables',
64
$t = $e->parse( load_file("t/pt-visual-explain/samples/impossible_having.sql") );
67
{ type => 'IMPOSSIBLE',
70
warning => 'Impossible HAVING',
75
$t = $e->parse( load_file("t/pt-visual-explain/samples/const_row_not_found.sql") );
78
{ type => 'UNION RESULT',
80
{ type => 'Constant table access',
84
warning => 'const row not found',
88
possible_keys => undef,
97
{ type => 'Table scan',
103
table => 'union(<none>,t12)',
104
possible_keys => undef,
107
{ type => 'SUBQUERY',
109
{ type => 'SUBQUERY',
113
{ type => 'IMPOSSIBLE',
119
{ type => 'Constant table access',
120
warning => 'const row not found',
128
possible_keys => undef,
140
'Const row not found',
143
$t = $e->parse( load_file("t/pt-visual-explain/samples/dual_union_in_subquery.sql") );
146
{ type => 'UNION RESULT',
153
type => 'DEPENDENT SUBQUERY',
156
{ type => 'Table scan',
163
possible_keys => undef,
164
table => 'union(<none>,<none>)',
167
type => 'DEPENDENT SUBQUERY',
171
type => 'DEPENDENT UNION',
182
'UNION of DUAL in a subquery',
185
$t = $e->parse( load_file("t/pt-visual-explain/samples/no_const_row.sql") );
188
{ type => 'Constant table access',
192
warning => 'const row not found',
196
possible_keys => undef,
201
'No constant row found',
204
$t = $e->parse( load_file("t/pt-visual-explain/samples/unique_row_not_found.sql") );
211
{ type => 'Bookmark lookup',
216
possible_keys => 'PRIMARY',
218
type => 'Constant index lookup',
221
key => 'user->PRIMARY'
223
{ possible_keys => 'PRIMARY',
230
{ type => 'Bookmark lookup',
232
warning => 'unique row not found',
236
possible_keys => 'PRIMARY',
238
type => 'Constant index lookup',
241
key => 'avatar->PRIMARY'
243
{ possible_keys => 'PRIMARY',
252
{ type => 'Bookmark lookup',
254
warning => 'unique row not found',
258
possible_keys => 'PRIMARY',
260
type => 'Constant index lookup',
263
key => 'customavatar->PRIMARY'
265
{ possible_keys => 'PRIMARY',
266
table => 'customavatar',
274
'Unique row not found',
277
$t = $e->parse( load_file("t/pt-visual-explain/samples/no_min_max_row.sql") );
280
{ type => 'IMPOSSIBLE',
281
warning => 'No matching min/max row',
288
$t = $e->parse( load_file("t/pt-visual-explain/samples/simple_partition.sql") );
291
{ type => 'Filesort',
295
{ type => 'Table scan',
300
possible_keys => undef,
301
partitions => 'p0,p1,p2,p3',
310
$t = $e->parse( load_file("t/pt-visual-explain/samples/full_scan_sakila_film.sql") );
313
{ type => 'Table scan',
320
possible_keys => undef,
328
$t = $e->parse( load_file("t/pt-visual-explain/samples/actor_join_film_ref.sql") );
333
{ type => 'Table scan',
340
possible_keys => 'PRIMARY',
345
{ type => 'Bookmark lookup',
349
{ type => 'Index lookup',
350
key => 'film_actor->idx_fk_film_id',
352
'ref' => 'sakila.film.film_id',
354
possible_keys => 'idx_fk_film_id',
358
table => 'film_actor',
359
possible_keys => 'idx_fk_film_id',
369
$t = $e->parse( load_file("t/pt-visual-explain/samples/join_buffer.sql") );
376
{ type => 'Table scan',
383
possible_keys => undef,
388
{ type => 'Filter with WHERE',
392
{ type => 'Bookmark lookup',
394
{ type => 'Index lookup',
397
'ref' => 'test.t1.col1',
399
possible_keys => 'key1',
404
possible_keys => 'key1',
413
{ type => 'Join buffer',
417
{ type => 'Filter with WHERE',
419
{ type => 'Bookmark lookup',
421
{ type => 'Index range scan',
426
possible_keys => 'key1',
431
possible_keys => 'key1',
442
'Three-way join with buffer',
445
$t = $e->parse( load_file("t/pt-visual-explain/samples/range_check.sql") );
450
{ type => 'Filter with WHERE',
454
{ type => 'Bookmark lookup',
456
{ type => 'Index lookup',
458
key => 'v->OXROOTID',
461
possible_keys => 'OXLEFT,OXRIGHT,OXROOTID',
466
possible_keys => 'OXLEFT,OXRIGHT,OXROOTID',
474
type => 'Re-evaluate indexes each row',
477
possible_keys => '3',
479
{ type => 'Table scan',
484
possible_keys => 'OXLEFT',
493
'Join that uses a range check',
497
$e->parse( load_file("t/pt-visual-explain/samples/range_check_3.sql") ),
499
'Key map same when decimal as when hex',
503
$e->parse( load_file("t/pt-visual-explain/samples/range_check_2.sql") ),
505
'Key map same as index map',
508
$t = $e->parse( load_file("t/pt-visual-explain/samples/not_exists.sql") );
513
{ type => 'Index scan',
517
key => 'film->idx_fk_language_id',
520
possible_keys => undef,
523
{ type => 'Distinct/Not-Exists',
527
{ type => 'Filter with WHERE',
529
{ type => 'Index lookup',
530
key => 'film_actor->idx_fk_film_id',
532
'ref' => 'sakila.film.film_id',
534
possible_keys => 'idx_fk_film_id',
543
'Join that uses Not exists',
546
$t = $e->parse( load_file("t/pt-visual-explain/samples/join_temporary_with_where_distinct.sql") );
551
{ type => 'Table scan',
556
{ type => 'TEMPORARY',
557
table => 'temporary(film)',
558
possible_keys => undef,
561
{ type => 'Filter with WHERE',
563
{ type => 'Table scan',
568
possible_keys => 'PRIMARY',
579
{ type => 'Distinct/Not-Exists',
583
{ type => 'Index lookup',
584
key => 'film_actor->idx_fk_film_id',
585
possible_keys => 'idx_fk_film_id',
588
'ref' => 'sakila.film.film_id',
595
'Join that uses a temp table, WHERE, and Distinct',
598
$t = $e->parse( load_file("t/pt-visual-explain/samples/simple_join_three_tables.sql") );
605
{ type => 'Index scan',
606
key => 'actor_1->PRIMARY',
607
possible_keys => 'PRIMARY',
615
{ type => 'Unique index lookup',
616
key => 'actor_2->PRIMARY',
617
possible_keys => 'PRIMARY',
620
'ref' => 'sakila.actor_1.actor_id',
627
{ type => 'Unique index lookup',
628
key => 'actor_3->PRIMARY',
629
possible_keys => 'PRIMARY',
632
'ref' => 'sakila.actor_1.actor_id',
639
'Simple join over three tables',
642
$t = $e->parse( load_file("t/pt-visual-explain/samples/film_join_actor_eq_ref.sql") );
647
{ type => 'Table scan',
653
table => 'film_actor',
654
possible_keys => 'idx_fk_film_id',
659
{ type => 'Bookmark lookup',
663
{ type => 'Unique index lookup',
664
key => 'film->PRIMARY',
666
'ref' => 'sakila.film_actor.film_id',
668
possible_keys => 'PRIMARY',
673
possible_keys => 'PRIMARY',
684
load_file("t/pt-visual-explain/samples/film_join_actor_eq_ref.sql"),
691
{ type => 'Table scan',
697
table => 'film_actor',
698
possible_keys => 'idx_fk_film_id',
703
{ type => 'Unique index lookup',
706
key => 'film->PRIMARY',
707
possible_keys => 'PRIMARY',
710
'ref' => 'sakila.film_actor.film_id',
715
'Straight join assuming clustered PK',
718
$t = $e->parse( load_file("t/pt-visual-explain/samples/full_row_pk_lookup_sakila_film.sql") );
721
{ type => 'Bookmark lookup',
725
{ type => 'Constant index lookup',
726
key => 'film->PRIMARY',
730
possible_keys => 'PRIMARY',
735
possible_keys => 'PRIMARY',
743
$t = $e->parse( load_file("t/pt-visual-explain/samples/index_scan_sakila_film.sql") );
746
{ type => 'Bookmark lookup',
750
{ type => 'Index scan',
751
key => 'film->idx_title',
755
possible_keys => undef,
760
possible_keys => undef,
768
$t = $e->parse( load_file("t/pt-visual-explain/samples/index_scan_sakila_film_using_where.sql") );
771
{ type => 'Filter with WHERE',
775
{ type => 'Bookmark lookup',
777
{ type => 'Index scan',
778
key => 'film->idx_title',
782
possible_keys => undef,
787
possible_keys => undef,
794
'Index scan with WHERE clause',
797
$t = $e->parse( load_file("t/pt-visual-explain/samples/pk_lookup_sakila_film.sql") );
800
{ type => 'Constant index lookup',
801
key => 'film->PRIMARY',
802
possible_keys => 'PRIMARY',
810
'PK lookup with covering index',
813
$t = $e->parse( load_file("t/pt-visual-explain/samples/film_join_actor_const.sql") );
818
{ type => 'Bookmark lookup',
822
{ type => 'Constant index lookup',
823
key => 'film->PRIMARY',
827
possible_keys => 'PRIMARY',
832
possible_keys => 'PRIMARY',
837
{ type => 'Bookmark lookup',
841
{ type => 'Index lookup',
842
key => 'film_actor->idx_fk_film_id',
846
possible_keys => 'idx_fk_film_id',
850
table => 'film_actor',
851
possible_keys => 'idx_fk_film_id',
858
'Join from constant lookup in film to const ref in film_actor',
861
$t = $e->parse( load_file("t/pt-visual-explain/samples/film_join_actor_const_using_index.sql") );
866
{ type => 'Constant index lookup',
867
key => 'film->PRIMARY',
868
possible_keys => 'PRIMARY',
876
{ type => 'Index lookup',
877
key => 'film_actor->idx_fk_film_id',
878
possible_keys => 'idx_fk_film_id',
888
'Join from const film to const ref film_actor with covering index',
891
$t = $e->parse( load_file("t/pt-visual-explain/samples/film_range_on_pk.sql") );
894
{ type => 'Filter with WHERE',
898
{ type => 'Bookmark lookup',
900
{ type => 'Index range scan',
901
key => 'film->PRIMARY',
905
possible_keys => 'PRIMARY',
910
possible_keys => 'PRIMARY',
917
'Index range scan with WHERE clause',
920
$t = $e->parse( load_file("t/pt-visual-explain/samples/loose_index_scan.sql") );
923
{ type => 'Loose index scan',
924
key => 'film->idx_fk_language_id',
930
possible_keys => undef,
937
load_file("t/pt-visual-explain/samples/film_ref_or_null_on_original_language_id.sql") );
940
{ type => 'Filter with WHERE',
944
{ type => 'Bookmark lookup',
946
{ type => 'Index lookup with extra null lookup',
947
key => 'film->idx_fk_original_language_id',
951
possible_keys => 'idx_fk_original_language_id',
956
possible_keys => 'idx_fk_original_language_id',
963
'Index ref_or_null scan',
966
$t = $e->parse( load_file("t/pt-visual-explain/samples/rental_index_merge_intersect.sql") );
969
{ type => 'Filter with WHERE',
973
{ type => 'Bookmark lookup',
975
{ type => 'Index merge',
976
method => 'intersect',
979
{ type => 'Index range scan',
980
key => 'rental->idx_fk_inventory_id',
982
'idx_fk_inventory_id,idx_fk_customer_id',
988
{ type => 'Index range scan',
989
key => 'rental->idx_fk_customer_id',
991
'idx_fk_inventory_id,idx_fk_customer_id',
1001
possible_keys => 'idx_fk_inventory_id,idx_fk_customer_id',
1002
partitions => undef,
1008
'Index intersection merge',
1011
$t = $e->parse( load_file("t/pt-visual-explain/samples/index_merge_three_keys.sql") );
1014
{ type => 'Filter with WHERE',
1018
{ type => 'Index merge',
1019
method => 'intersect',
1022
{ type => 'Index range scan',
1024
possible_keys => 'key1,key2,key3',
1025
partitions => undef,
1030
{ type => 'Index range scan',
1032
possible_keys => 'key1,key2,key3',
1033
partitions => undef,
1038
{ type => 'Index range scan',
1040
possible_keys => 'key1,key2,key3',
1041
partitions => undef,
1050
'Index intersection merge with three keys and covering index',
1053
$t = $e->parse( load_file("t/pt-visual-explain/samples/index_merge_union_intersect.sql") );
1056
{ type => 'Filter with WHERE',
1060
{ type => 'Bookmark lookup',
1062
{ type => 'Index merge',
1066
{ type => 'Index merge',
1067
method => 'intersect',
1070
{ type => 'Index range scan',
1072
possible_keys => 'key1,key2,key3,key4',
1073
partitions => undef,
1078
{ type => 'Index range scan',
1080
possible_keys => 'key1,key2,key3,key4',
1081
partitions => undef,
1088
{ type => 'Index merge',
1089
method => 'intersect',
1092
{ type => 'Index range scan',
1094
possible_keys => 'key1,key2,key3,key4',
1095
partitions => undef,
1100
{ type => 'Index range scan',
1102
possible_keys => 'key1,key2,key3,key4',
1103
partitions => undef,
1114
possible_keys => 'key1,key2,key3,key4',
1115
partitions => undef,
1121
'Index merge union-intersection',
1124
$t = $e->parse( load_file("t/pt-visual-explain/samples/index_merge_sort_union.sql") );
1127
{ type => 'Filter with WHERE',
1131
{ type => 'Bookmark lookup',
1133
{ type => 'Index merge',
1134
method => 'sort_union',
1137
{ type => 'Index range scan',
1139
possible_keys => 'i1,i2',
1140
partitions => undef,
1145
{ type => 'Index range scan',
1147
possible_keys => 'i1,i2',
1148
partitions => undef,
1157
possible_keys => 'i1,i2',
1158
partitions => undef,
1164
'Index merge sort_union',
1167
$t = $e->parse( load_file("t/pt-visual-explain/samples/optimized_away.sql") );
1170
{ type => 'CONSTANT',
1174
'No tables used - constant',
1177
$t = $e->parse( load_file("t/pt-visual-explain/samples/no_from.sql") );
1184
'No tables used - no FROM',
1187
$t = $e->parse( load_file("t/pt-visual-explain/samples/filesort.sql") );
1190
{ type => 'Filesort',
1194
{ type => 'Table scan',
1199
possible_keys => undef,
1200
partitions => undef,
1209
$t = $e->parse( load_file("t/pt-visual-explain/samples/temporary_filesort.sql") );
1212
{ type => 'Filesort',
1214
{ type => 'TEMPORARY',
1215
table => 'temporary(film)',
1216
possible_keys => undef,
1217
partitions => undef,
1219
{ type => 'Index scan',
1220
key => 'film->PRIMARY',
1221
possible_keys => undef,
1222
partitions => undef,
1233
'Filesort with temporary',
1236
$t = $e->parse( load_file("t/pt-visual-explain/samples/filesort_on_subsequent_tbl.sql") );
1243
{ type => 'Constant table access',
1249
table => 'const_tbl',
1250
possible_keys => undef,
1251
partitions => undef,
1255
{ type => 'Filesort',
1259
{ type => 'Filter with WHERE',
1261
{ type => 'Table scan',
1266
partitions => undef,
1267
possible_keys => undef,
1277
{ type => 'Filter with WHERE',
1281
{ type => 'Bookmark lookup',
1283
{ type => 'Index lookup',
1286
possible_keys => 'a',
1287
ref => 'test4.t1.a',
1289
partitions => undef,
1293
possible_keys => 'a',
1294
partitions => undef,
1302
'Filesort on first non-constant table',
1305
$t = $e->parse( load_file("t/pt-visual-explain/samples/three_table_join_with_temp_filesort.sql") );
1308
{ type => 'Filesort',
1310
{ type => 'TEMPORARY',
1311
partitions => undef,
1312
possible_keys => undef,
1313
table => 'temporary(actor,film_actor,film)',
1319
{ type => 'Index scan',
1320
key => 'actor->PRIMARY',
1321
possible_keys => 'PRIMARY',
1325
partitions => undef,
1329
{ type => 'Index lookup',
1330
key => 'film_actor->PRIMARY',
1332
ref => 'sakila.actor.actor_id',
1334
partitions => undef,
1335
possible_keys => 'PRIMARY,idx_fk_film_id',
1341
{ type => 'Unique index lookup',
1342
key => 'film->PRIMARY',
1343
possible_keys => 'PRIMARY',
1345
ref => 'sakila.film_actor.film_id',
1347
partitions => undef,
1357
'Filesort with temporary',
1361
$t = $e->parse( load_file("t/pt-visual-explain/samples/too_many_unions.sql") );
1363
like($EVAL_ERROR, qr/UNION has too many tables/, 'Too many unions');
1366
$t = $e->parse( load_file("t/pt-visual-explain/samples/simple_union.sql") );
1369
{ type => 'Table scan',
1375
possible_keys => undef,
1376
partitions => undef,
1377
table => 'union(actor_1,actor_2)',
1379
{ type => 'Index scan',
1380
key => 'actor_1->PRIMARY',
1381
possible_keys => undef,
1382
partitions => undef,
1389
{ type => 'Index scan',
1390
key => 'actor_2->PRIMARY',
1391
possible_keys => undef,
1392
partitions => undef,
1406
$t = $e->parse( load_file("t/pt-visual-explain/samples/derived_over_bookmark_lookup.sql") );
1409
{ type => 'Table scan',
1414
{ type => 'DERIVED',
1415
table => 'derived(film_actor)',
1416
possible_keys => undef,
1417
partitions => undef,
1419
{ type => 'Bookmark lookup',
1423
{ type => 'Index lookup',
1424
key => 'film_actor->idx_fk_film_id',
1425
possible_keys => 'idx_fk_film_id',
1426
partitions => undef,
1432
table => 'film_actor',
1433
possible_keys => 'idx_fk_film_id',
1434
partitions => undef,
1442
'Derived table over a bookmark lookup',
1445
$t = $e->parse( load_file("t/pt-visual-explain/samples/simple_derived.sql") );
1448
{ type => 'Table scan',
1453
{ type => 'DERIVED',
1454
table => 'derived(actor)',
1455
possible_keys => undef,
1456
partitions => undef,
1458
{ type => 'Index scan',
1459
key => 'actor->PRIMARY',
1460
possible_keys => undef,
1461
partitions => undef,
1472
'Simple derived table',
1475
$t = $e->parse( load_file("t/pt-visual-explain/samples/derived_over_join.sql") );
1478
{ type => 'Table scan',
1483
{ type => 'DERIVED',
1484
table => 'derived(actor_1,actor_2)',
1485
possible_keys => undef,
1486
partitions => undef,
1490
{ type => 'Index scan',
1491
key => 'actor_1->PRIMARY',
1492
possible_keys => undef,
1493
partitions => undef,
1500
{ type => 'Index scan',
1501
key => 'actor_2->PRIMARY',
1502
possible_keys => undef,
1503
partitions => undef,
1516
'Simple derived table over a simple join',
1519
$t = $e->parse( load_file("t/pt-visual-explain/samples/join_two_derived_tables_of_joins.sql") );
1524
{ type => 'Table scan',
1529
{ type => 'DERIVED',
1530
table => 'derived(actor_1,actor_2)',
1531
possible_keys => undef,
1532
partitions => undef,
1536
{ type => 'Index scan',
1537
key => 'actor_1->PRIMARY',
1538
possible_keys => undef,
1539
partitions => undef,
1546
{ type => 'Index scan',
1547
key => 'actor_2->PRIMARY',
1548
possible_keys => undef,
1549
partitions => undef,
1562
{ type => 'Filter with WHERE',
1566
{ type => 'Table scan',
1569
{ type => 'DERIVED',
1570
table => 'derived(actor_3,actor_4)',
1571
possible_keys => undef,
1572
partitions => undef,
1576
{ type => 'Index scan',
1577
key => 'actor_3->PRIMARY',
1578
possible_keys => undef,
1579
partitions => undef,
1586
{ type => 'Index scan',
1587
key => 'actor_4->PRIMARY',
1588
possible_keys => undef,
1589
partitions => undef,
1606
'Join two derived tables which each contain a join',
1609
$t = $e->parse( load_file("t/pt-visual-explain/samples/union_of_derived_tables.sql") );
1612
{ type => 'Table scan',
1618
table => 'union(derived(actor),derived(film))',
1619
possible_keys => undef,
1620
partitions => undef,
1622
{ type => 'Table scan',
1627
{ type => 'DERIVED',
1628
table => 'derived(actor)',
1629
possible_keys => undef,
1630
partitions => undef,
1632
{ type => 'Index scan',
1633
key => 'actor->PRIMARY',
1634
possible_keys => undef,
1635
partitions => undef,
1646
{ type => 'Table scan',
1651
{ type => 'DERIVED',
1652
table => 'derived(film)',
1653
possible_keys => undef,
1654
partitions => undef,
1656
{ type => 'Index scan',
1657
key => 'film->idx_fk_language_id',
1658
possible_keys => undef,
1659
partitions => undef,
1674
'Union over two derived tables',
1677
$t = $e->parse( load_file("t/pt-visual-explain/samples/join_two_derived_tables_of_unions.sql") );
1682
{ type => 'Constant table access',
1687
{ type => 'DERIVED',
1688
table => 'derived(union(actor_1,actor_2))',
1689
possible_keys => undef,
1690
partitions => undef,
1692
{ type => 'Table scan',
1698
possible_keys => undef,
1699
partitions => undef,
1700
table => 'union(actor_1,actor_2)',
1702
{ type => 'Index scan',
1703
key => 'actor_1->PRIMARY',
1704
possible_keys => undef,
1705
partitions => undef,
1712
{ type => 'Index scan',
1713
key => 'actor_2->PRIMARY',
1714
possible_keys => undef,
1715
partitions => undef,
1730
{ type => 'Constant table access',
1735
{ type => 'DERIVED',
1736
table => 'derived(union(actor_3,actor_4))',
1737
possible_keys => undef,
1738
partitions => undef,
1740
{ type => 'Table scan',
1746
possible_keys => undef,
1747
partitions => undef,
1748
table => 'union(actor_3,actor_4)',
1750
{ type => 'Index scan',
1751
key => 'actor_3->PRIMARY',
1752
possible_keys => undef,
1753
partitions => undef,
1760
{ type => 'Index scan',
1761
key => 'actor_4->PRIMARY',
1762
possible_keys => undef,
1763
partitions => undef,
1780
'Join over two derived tables of unions',
1783
$t = $e->parse( load_file("t/pt-visual-explain/samples/union_of_derived_unions.sql") );
1786
{ type => 'Table scan',
1793
'union(derived(union(actor_1,actor_2)),derived(union(actor_3,actor_4)))',
1794
possible_keys => undef,
1795
partitions => undef,
1797
{ type => 'Constant table access',
1802
{ type => 'DERIVED',
1803
table => 'derived(union(actor_1,actor_2))',
1804
possible_keys => undef,
1805
partitions => undef,
1807
{ type => 'Table scan',
1813
possible_keys => undef,
1814
partitions => undef,
1815
table => 'union(actor_1,actor_2)',
1817
{ type => 'Index scan',
1818
key => 'actor_1->PRIMARY',
1819
possible_keys => undef,
1820
partitions => undef,
1827
{ type => 'Index scan',
1828
key => 'actor_2->PRIMARY',
1829
possible_keys => undef,
1830
partitions => undef,
1845
{ type => 'Table scan',
1850
{ type => 'DERIVED',
1851
table => 'derived(union(actor_3,actor_4))',
1852
possible_keys => undef,
1853
partitions => undef,
1855
{ type => 'Table scan',
1861
possible_keys => undef,
1862
partitions => undef,
1863
table => 'union(actor_3,actor_4)',
1865
{ type => 'Index scan',
1866
key => 'actor_3->PRIMARY',
1867
possible_keys => undef,
1868
partitions => undef,
1875
{ type => 'Index scan',
1876
key => 'actor_4->PRIMARY',
1877
possible_keys => undef,
1878
partitions => undef,
1897
'Union over two derived tables of unions',
1900
$t = $e->parse( load_file("t/pt-visual-explain/samples/simple_subquery.sql") );
1903
{ type => 'SUBQUERY',
1905
{ type => 'Index scan',
1910
key => 'actor->PRIMARY',
1911
possible_keys => undef,
1912
partitions => undef,
1915
{ type => 'Index scan',
1916
key => 'film->idx_fk_language_id',
1917
possible_keys => undef,
1918
partitions => undef,
1930
$t = $e->parse( load_file("t/pt-visual-explain/samples/dependent_subquery.sql") );
1933
{ type => 'DEPENDENT SUBQUERY',
1935
{ type => 'Index scan',
1940
key => 'actor->PRIMARY',
1941
possible_keys => undef,
1942
partitions => undef,
1945
{ type => 'Filter with WHERE',
1949
{ type => 'Index lookup',
1950
key => 'film_actor->PRIMARY',
1951
possible_keys => 'PRIMARY',
1952
partitions => undef,
1954
'ref' => 'actor.actor_id',
1961
'Dependent subquery',
1964
$t = $e->parse( load_file("t/pt-visual-explain/samples/uncacheable_subquery.sql") );
1967
{ type => 'UNCACHEABLE SUBQUERY',
1969
{ type => 'Index scan',
1974
key => 'actor->PRIMARY',
1975
possible_keys => undef,
1976
partitions => undef,
1979
{ type => 'Index scan',
1980
key => 'actor->PRIMARY',
1981
possible_keys => undef,
1982
partitions => undef,
1991
'Dependent uncacheable subquery',
1994
$t = $e->parse( load_file("t/pt-visual-explain/samples/join_in_subquery.sql") );
1997
{ type => 'SUBQUERY',
1999
{ type => 'Index scan',
2004
key => 'actor->PRIMARY',
2005
possible_keys => undef,
2006
partitions => undef,
2011
{ type => 'Index scan',
2012
key => 'film->idx_fk_language_id',
2014
possible_keys => 'PRIMARY',
2015
partitions => undef,
2021
{ type => 'Index lookup',
2022
key => 'film_actor->idx_fk_film_id',
2023
possible_keys => 'idx_fk_film_id',
2024
partitions => undef,
2026
'ref' => 'sakila.film.film_id',
2035
'Join inside a subquery',
2038
$t = $e->parse( load_file("t/pt-visual-explain/samples/unique_subquery_in_where_clause.sql") );
2041
{ type => 'DEPENDENT SUBQUERY',
2043
{ type => 'Filter with WHERE',
2047
{ type => 'Index scan',
2050
key => 'film_actor->idx_fk_film_id',
2051
possible_keys => undef,
2052
partitions => undef,
2057
{ type => 'Unique subquery',
2062
key => 'actor->PRIMARY',
2063
possible_keys => 'PRIMARY',
2064
partitions => undef,
2072
$t = $e->parse( load_file("t/pt-visual-explain/samples/index_subquery_in_where_clause.sql") );
2075
{ type => 'DEPENDENT SUBQUERY',
2077
{ type => 'Filter with WHERE',
2081
{ type => 'Index scan',
2084
key => 'actor->PRIMARY',
2085
possible_keys => undef,
2086
partitions => undef,
2091
{ type => 'Index subquery',
2096
key => 'film_actor->PRIMARY',
2097
possible_keys => 'PRIMARY',
2098
partitions => undef,
2106
$t = $e->parse( load_file("t/pt-visual-explain/samples/full_scan_on_null_key.sql") );
2109
{ type => 'DEPENDENT SUBQUERY',
2111
{ type => 'Filter with WHERE',
2115
{ type => 'Table scan',
2120
possible_keys => undef,
2121
partitions => undef,
2129
{ type => 'Filter with WHERE',
2133
{ type => 'Unique index lookup',
2136
key => 't2->PRIMARY',
2137
possible_keys => 'PRIMARY',
2138
partitions => undef,
2140
warning => 'Full scan on NULL key',
2144
{ type => 'Filter with WHERE',
2148
{ type => 'Bookmark lookup',
2150
{ type => 'Unique index lookup',
2153
key => 't3->PRIMARY',
2155
warning => 'Full scan on NULL key',
2156
possible_keys => 'PRIMARY',
2157
partitions => undef,
2161
possible_keys => 'PRIMARY',
2162
partitions => undef,
2172
'Subqueries that do a full scan on a NULL key',
2175
$t = $e->parse( load_file("t/pt-visual-explain/samples/nested_derived_tables.sql") );
2178
{ type => 'DEPENDENT SUBQUERY',
2180
{ type => 'Table scan',
2185
{ type => 'DERIVED',
2186
table => 'derived(derived(inner_der,inner_sub),mid_sub)',
2187
possible_keys => undef,
2188
partitions => undef,
2190
{ type => 'DEPENDENT SUBQUERY',
2192
{ type => 'Table scan',
2197
{ type => 'DERIVED',
2198
table => 'derived(inner_der,inner_sub)',
2199
possible_keys => undef,
2200
partitions => undef,
2202
{ type => 'DEPENDENT SUBQUERY',
2204
{ type => 'Table scan',
2210
table => 'inner_der',
2211
possible_keys => undef,
2212
partitions => undef,
2216
{ type => 'Filter with WHERE',
2220
{ type => 'Unique index lookup',
2223
key => 'inner_sub->PRIMARY',
2224
possible_keys => 'PRIMARY',
2225
partitions => undef,
2226
'ref' => 'inner_der.film_id',
2236
{ type => 'Filter with WHERE',
2240
{ type => 'Unique index lookup',
2243
key => 'mid_sub->PRIMARY',
2244
possible_keys => 'PRIMARY',
2245
partitions => undef,
2246
'ref' => 'mid_der.film_id',
2256
{ type => 'Filter with WHERE',
2260
{ type => 'Unique index lookup',
2263
key => 'outer_sub->PRIMARY',
2264
possible_keys => 'PRIMARY',
2265
partitions => undef,
2266
'ref' => 'outer_der.film_id',
2272
'Nested derived tables and subqueries',
2275
$t = $e->parse( load_file("t/pt-visual-explain/samples/adjacent_subqueries.sql") );
2278
{ type => 'DEPENDENT SUBQUERY',
2280
{ type => 'SUBQUERY',
2282
{ type => 'Index scan',
2283
key => 'actor->PRIMARY',
2287
partitions => undef,
2288
possible_keys => undef,
2292
{ type => 'Index scan',
2293
key => 'f->idx_fk_language_id',
2297
partitions => undef,
2298
possible_keys => undef,
2304
{ type => 'Filter with WHERE',
2308
{ type => 'Index lookup',
2309
key => 'film_actor->PRIMARY',
2310
possible_keys => 'PRIMARY',
2311
partitions => undef,
2313
'ref' => 'actor.actor_id',
2320
'Adjacent subqueries',
2323
$t = $e->parse( load_file("t/pt-visual-explain/samples/complex_select_types.sql") );
2327
type => 'Table scan',
2331
{ possible_keys => undef,
2332
table => 'union(derived(actor),film_actor,derived(film,store),rental)',
2334
partitions => undef,
2336
{ type => 'DEPENDENT SUBQUERY',
2339
type => 'Table scan',
2343
{ possible_keys => undef,
2344
table => 'derived(actor)',
2346
partitions => undef,
2351
partitions => undef,
2353
key => 'actor->PRIMARY',
2354
possible_keys => undef,
2355
type => 'Index scan',
2363
ref => 'der_1.actor_id',
2365
partitions => undef,
2367
key => 'film_actor->PRIMARY',
2368
possible_keys => 'PRIMARY',
2369
type => 'Index lookup',
2374
{ type => 'UNCACHEABLE SUBQUERY',
2377
type => 'Table scan',
2381
{ possible_keys => undef,
2382
table => 'derived(film,store)',
2384
partitions => undef,
2386
{ type => 'SUBQUERY',
2391
partitions => undef,
2393
key => 'film->idx_fk_language_id',
2394
possible_keys => undef,
2395
type => 'Index scan',
2401
partitions => undef,
2403
key => 'store->PRIMARY',
2404
possible_keys => undef,
2405
type => 'Index scan',
2417
partitions => undef,
2419
key => 'rental->idx_fk_staff_id',
2420
possible_keys => undef,
2421
type => 'Index scan',
2430
'Complex SELECT types combined',
2433
$t = $e->parse( load_file("t/pt-visual-explain/samples/derived_without_table.sql") );
2437
type => 'Constant table access',
2441
{ possible_keys => undef,
2442
table => 'derived(<none>)',
2444
partitions => undef,
2454
'Recursive table name with anonymous derived table',
2457
# #############################################################################
2459
# #############################################################################