File: idx_compare_setup_index_test.inc

package info (click to toggle)
mysql-8.0 8.0.43-3
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 1,273,924 kB
  • sloc: cpp: 4,684,605; ansic: 412,450; pascal: 108,398; java: 83,641; perl: 30,221; cs: 27,067; sql: 26,594; sh: 24,181; python: 21,816; yacc: 17,169; php: 11,522; xml: 7,388; javascript: 7,076; makefile: 2,194; lex: 1,075; awk: 670; asm: 520; objc: 183; ruby: 97; lisp: 86
file content (136 lines) | stat: -rw-r--r-- 4,773 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
#
# Performance Schema, Index validation
#

--echo
--echo ## Create index_test() procedure
--disable_warnings
DROP PROCEDURE IF EXISTS index_test;
--enable_warnings


--disable_query_log

# This procedure executes a SELECT for the given table, once with indexes disabled
# and again with indexes enabled. The two result sets are compared.
#
# 1. Run query with no indexes "USE INDEX ()".
# 2. Save results in temporary table, prefix rows with sequence number.
# 3. Run queries with indexes enabled.
# 4. Save results in temporary table, prefix rows with sequence number.
# 5. Compare tables for extra or missing rows with a JOIN on the sequence number.
#
# Parameters:
#    table_name    - Name of table
#    where_clause  - WHERE clause with indexes

DELIMITER $$;
CREATE PROCEDURE index_test(IN table_name VARCHAR(1024),
                            IN where_clause VARCHAR(1024))
BEGIN
  DROP TABLE IF EXISTS test.indexes_off;
  SET @table_name = table_name;
  SET @where_clause = where_clause;

  # Tables such as events_errors with TIMESTAMP columns, using "*" for the
  # result set tables fails with "1067: Invalid default value for 'FIRST_SEEN'".
  # As a workaround, specify only the necessary columns.

  ## Indexes disabled ##
 
  # Create table from result set with autoincremented sequence for each row (use AUTOINC?)
  SET @row:=0;
  SET @query_no_idx = CONCAT("SELECT ", @pfs_columns," FROM performance_schema.", @table_name, " USE INDEX () ", @where_clause);
  SET @main_query = CONCAT("CREATE TABLE test.indexes_off AS (SELECT @row:=@row+1 SEQ, output.* FROM (", @query_no_idx, ") output);");

  PREPARE stmt1 FROM @main_query;
  EXECUTE stmt1;
  DEALLOCATE PREPARE stmt1;
  # Index the sequence column -- needed for large joins
  ALTER TABLE test.indexes_off ADD INDEX (seq);

  ## Indexes enabled ##

  # Record the initial handler_read_key count
  FLUSH STATUS;
  SELECT variable_value INTO @read_key_before FROM performance_schema.session_status USE INDEX() WHERE variable_name = "handler_read_key";
  SET @read_key_before := @read_key_before + 0;

  DROP TABLE IF EXISTS test.indexes_on;
  SET @row:=0;
  SET @query = CONCAT("SELECT ", @pfs_columns," FROM performance_schema.", @table_name, " ", @where_clause);
  SET @main_query = CONCAT("CREATE TABLE test.indexes_on AS (SELECT @row:=@row+1 SEQ, output.* FROM (", @query, ") output);");
  SET @explain = CONCAT("EXPLAIN ", @query);
  SELECT @query AS "========";

  PREPARE stmt2 FROM @main_query;
  EXECUTE stmt2;
  DEALLOCATE PREPARE stmt2;
  
  # Record the final handler_read_key count
  SELECT variable_value INTO @read_key_after FROM performance_schema.session_status USE INDEX() WHERE variable_name = "handler_read_key";
  SET @read_key_after := @read_key_after + 0;
  
  # Index the sequence column -- needed for large joins
  ALTER TABLE test.indexes_on ADD INDEX (seq);

  #PREPARE stmt3 FROM @explain;
  #EXECUTE stmt3;
  #DEALLOCATE PREPARE stmt3;

  #DEBUG
  #SELECT * FROM test.indexes_off;
  #SELECT * FROM test.indexes_on;

  ## Verify that the indexes were used
  
  IF (@read_key_before >= @read_key_after) THEN
    SET @msg = CONCAT('*** ERROR *** Handler_read_key before: ', @read_key_before, '  After: ', @read_key_after);
  ELSE
    SET @msg = "OK: Handler_read_key";
    #DEBUG SET @msg = CONCAT('OK: Handler_read_key before: ', @read_key_before, '  After: ', @read_key_after);
  END IF;
  SELECT @msg AS "";

  ## Verify that the expected result set was generated

  SELECT COUNT(*) > 0 INTO @expected FROM test.indexes_off;
  SELECT COUNT(*) > 0 INTO @actual FROM test.indexes_on;

  IF @expected = 1 THEN
    SET @result_set = "Non-empty";
    SET @bad_result_set = "Empty";
  ELSE
    SET @result_set = "Empty";
    SET @bad_result_set = "Non-empty";
  END IF;

  IF @actual != @expected THEN
    SET @result = CONCAT('*** ERROR ***: Result set: ', @bad_result_set, '  Expected: ', @result_set);
  ELSE
    SET @result = CONCAT('OK: Result set: ', @result_set, '  Expected: ', @result_set);
  END IF;

  SELECT @result AS "";

  ## Check for extra or missing rows

  SELECT COUNT(*) INTO @extra_rows FROM test.indexes_off indexes_off LEFT JOIN test.indexes_on ON (indexes_off.seq = indexes_on.seq) WHERE indexes_on.seq IS NULL;
  SELECT COUNT(*) INTO @missing_rows FROM test.indexes_on indexes_on RIGHT JOIN test.indexes_off ON (indexes_on.seq = indexes_off.seq) WHERE indexes_off.seq IS NULL;

  SET @result = "OK: ";
  IF (@extra_rows > 0) OR (@missing_rows > 0) THEN
    SET @result = "*** ERROR ***: ";
  END IF;
  SET @rows = CONCAT(@result, 'Extra rows: ', @extra_rows, '  Missing rows: ', @missing_rows);
  SELECT @rows AS "";

  ## Compare checksums
  #CHECKSUM TABLE test.indexes_off;
  #CHECKSUM TABLE test.indexes_on;

  END$$
DELIMITER ;$$

--enable_query_log