137 lines
4.7 KiB
SQL
137 lines
4.7 KiB
SQL
#
|
|
# 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
|
|
|