1
0
mirror of https://github.com/MariaDB/server.git synced 2025-07-29 05:21:33 +03:00

MDEV-12255 innodb_prefix_index_cluster_optimization hits debug build

assert on UTF-8 columns

Problem:
=======
(1) Multi-byte character cases are not considered during prefix index
cluster optimization check. It leads to fetch of improper results during
read operation.
(2) Strict assert in row_sel_field_store_in_mysql_format_func and it asserts
for prefix index record to mysql conversion.

Solution:
========
(1) Consider the case of multi-byte character during prefix index
cluster optimization check.
(2) Relax the assert in row_sel_field_store_in_mysql_format_func to allow
prefix index record to mysql format conversion.

The patch is taken from
1eee538087
This commit is contained in:
Thirunarayanan Balathandayuthapani
2018-03-20 17:51:57 +05:30
parent bc2e7d7889
commit eee73ddfbb
4 changed files with 1155 additions and 233 deletions

View File

@ -30,73 +30,372 @@ id fake_id bigfield
33 1033 yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy
128 1128 zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz
# Baseline sanity check: 0, 0.
select "no-op query";
no-op query
no-op query
cluster_lookups_matched
1
cluster_lookups_avoided_matched
1
select @cluster_lookups;
@cluster_lookups
0
select @cluster_lookups_avoided;
@cluster_lookups_avoided
0
# Eligible for optimization.
select id, bigfield from prefixinno where bigfield = repeat('d', 31);
id bigfield
31 ddddddddddddddddddddddddddddddd
cluster_lookups_matched
1
cluster_lookups_avoided_matched
select @cluster_lookups;
@cluster_lookups
0
select @cluster_lookups_avoided;
@cluster_lookups_avoided
1
# Eligible for optimization, access via fake_id only.
select id, bigfield from prefixinno where fake_id = 1031;
id bigfield
31 ddddddddddddddddddddddddddddddd
cluster_lookups_matched
1
cluster_lookups_avoided_matched
select @cluster_lookups;
@cluster_lookups
0
select @cluster_lookups_avoided;
@cluster_lookups_avoided
1
# Not eligible for optimization, access via fake_id of big row.
select id, bigfield from prefixinno where fake_id = 1033;
id bigfield
33 yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy
cluster_lookups_matched
1
cluster_lookups_avoided_matched
select @cluster_lookups;
@cluster_lookups
1
select @cluster_lookups_avoided;
@cluster_lookups_avoided
0
# Not eligible for optimization.
select id, bigfield from prefixinno where bigfield = repeat('x', 32);
id bigfield
32 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
cluster_lookups_matched
1
cluster_lookups_avoided_matched
select @cluster_lookups;
@cluster_lookups
1
select @cluster_lookups_avoided;
@cluster_lookups_avoided
0
# Not eligible for optimization.
select id, bigfield from prefixinno where bigfield = repeat('y', 33);
id bigfield
33 yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy
cluster_lookups_matched
1
cluster_lookups_avoided_matched
select @cluster_lookups;
@cluster_lookups
1
select @cluster_lookups_avoided;
@cluster_lookups_avoided
0
# Eligible, should not increment lookup counter.
select id, bigfield from prefixinno where bigfield = repeat('b', 8);
id bigfield
8 bbbbbbbb
cluster_lookups_matched
1
cluster_lookups_avoided_matched
select @cluster_lookups;
@cluster_lookups
0
select @cluster_lookups_avoided;
@cluster_lookups_avoided
1
# Eligible, should not increment lookup counter.
select id, bigfield from prefixinno where bigfield = repeat('c', 24);
id bigfield
24 cccccccccccccccccccccccc
cluster_lookups_matched
1
cluster_lookups_avoided_matched
select @cluster_lookups;
@cluster_lookups
0
select @cluster_lookups_avoided;
@cluster_lookups_avoided
1
# Should increment lookup counter.
select id, bigfield from prefixinno where bigfield = repeat('z', 128);
id bigfield
128 zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz
cluster_lookups_matched
1
cluster_lookups_avoided_matched
select @cluster_lookups;
@cluster_lookups
1
select @cluster_lookups_avoided;
@cluster_lookups_avoided
0
# Disable optimization, confirm we still increment counter.
set global innodb_prefix_index_cluster_optimization = OFF;
select id, bigfield from prefixinno where fake_id = 1033;
id bigfield
33 yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy
cluster_lookups_matched
select @cluster_lookups;
@cluster_lookups
1
cluster_lookups_avoided_matched
select @cluster_lookups_avoided;
@cluster_lookups_avoided
0
drop table prefixinno;
# Multi-byte handling case
set global innodb_prefix_index_cluster_optimization = ON;
SET NAMES utf8mb4;
CREATE TABLE t1(
f1 varchar(10) CHARACTER SET UTF8MB4 COLLATE UTF8MB4_BIN,
INDEX (f1(3)))ENGINE=INNODB;
INSERT INTO t1 VALUES('a'), ('cccc'), ('až'), ('cčc'), ('ggᵷg'), ('¢¢');
INSERT INTO t1 VALUES('தமிழ்'), ('🐱🌑'), ('🌒'), ('🌑');
INSERT INTO t1 VALUES('😊me'), ('eu€'), ('ls¢');
# Eligible - record length is shorter than prefix
SELECT f1 FROM t1 FORCE INDEX (`f1`) WHERE f1 = 'a';
f1
a
select @cluster_lookups;
@cluster_lookups
0
select @cluster_lookups_avoided;
@cluster_lookups_avoided
1
# make test suite happy by cleaning up our mess
# Not eligible - record length longer than prefix length
SELECT f1 FROM t1 FORCE INDEX (`f1`) WHERE f1 like 'c%';
f1
cccc
cčc
select @cluster_lookups;
@cluster_lookups
3
select @cluster_lookups_avoided;
@cluster_lookups_avoided
0
# Eligible - record length shorter than prefix length
SELECT f1 FROM t1 FORCE INDEX (`f1`) WHERE f1 = 'až';
f1
select @cluster_lookups;
@cluster_lookups
0
select @cluster_lookups_avoided;
@cluster_lookups_avoided
1
# Not eligible - record length longer than prefix length
SELECT f1 FROM t1 FORCE INDEX (`f1`) WHERE f1 = 'தமிழ்';
f1
தமிழ்
select @cluster_lookups;
@cluster_lookups
1
select @cluster_lookups_avoided;
@cluster_lookups_avoided
0
# Not eligible - record length longer than prefix length
SELECT f1 FROM t1 FORCE INDEX (`f1`) WHERE f1 like 'ggᵷ%';
f1
ggᵷg
select @cluster_lookups;
@cluster_lookups
1
select @cluster_lookups_avoided;
@cluster_lookups_avoided
0
# Not eligible - record length longer than prefix length
SELECT f1 FROM t1 FORCE INDEX (`f1`) WHERE f1 like '😊%';
f1
😊me
select @cluster_lookups;
@cluster_lookups
1
select @cluster_lookups_avoided;
@cluster_lookups_avoided
0
# Not eligible - record length longer than prefix length
SELECT f1 FROM t1 FORCE INDEX (`f1`) WHERE f1 = 'ls¢';
f1
ls¢
select @cluster_lookups;
@cluster_lookups
1
select @cluster_lookups_avoided;
@cluster_lookups_avoided
0
# Eligible - record length shorter than prefix length
SELECT f1 FROM t1 FORCE INDEX (`f1`) WHERE f1 like '¢¢%';
f1
¢¢
select @cluster_lookups;
@cluster_lookups
1
select @cluster_lookups_avoided;
@cluster_lookups_avoided
1
# Eligible - record length shorter than prefix length
SELECT f1 FROM t1 FORCE INDEX (`f1`) WHERE f1 like '🐱🌑%';
f1
🐱🌑
select @cluster_lookups;
@cluster_lookups
1
select @cluster_lookups_avoided;
@cluster_lookups_avoided
1
# Not eligible - record length longer than prefix length
SELECT f1 FROM t1 FORCE INDEX (`f1`) WHERE f1 like '🌑%';
f1
🌑
select @cluster_lookups;
@cluster_lookups
0
select @cluster_lookups_avoided;
@cluster_lookups_avoided
2
# Not eligible - record length longer than prefix length
SELECT f1 FROM t1 FORCE INDEX (`f1`) WHERE f1 like '🌒%';
f1
🌒
select @cluster_lookups;
@cluster_lookups
0
select @cluster_lookups_avoided;
@cluster_lookups_avoided
2
DROP TABLE t1;
# Multi-byte with minimum character length > 1 bytes
CREATE TABLE t1(
f1 varchar(10) CHARACTER SET UTF16 COLLATE UTF16_BIN,
INDEX (f1(3)))ENGINE=INNODB;
INSERT INTO t1 VALUES('a'), ('cccc'), ('až'), ('cčc'), ('ggᵷg'), ('¢¢');
INSERT INTO t1 VALUES('தமிழ்'), ('🐱🌑'), ('🌒'), ('🌑');
INSERT INTO t1 VALUES('😊me'), ('eu€'), ('ls¢');
# Eligible - record length is shorter than prefix
SELECT f1 FROM t1 FORCE INDEX (`f1`) WHERE f1 = 'a';
f1
a
select @cluster_lookups;
@cluster_lookups
0
select @cluster_lookups_avoided;
@cluster_lookups_avoided
1
# Not eligible - record length longer than prefix length
SELECT f1 FROM t1 FORCE INDEX (`f1`) WHERE f1 like 'c%';
f1
cccc
cčc
select @cluster_lookups;
@cluster_lookups
3
select @cluster_lookups_avoided;
@cluster_lookups_avoided
0
# Eligible - record length shorter than prefix length
SELECT f1 FROM t1 FORCE INDEX (`f1`) WHERE f1 = 'až';
f1
select @cluster_lookups;
@cluster_lookups
0
select @cluster_lookups_avoided;
@cluster_lookups_avoided
1
# Not eligible - record length longer than prefix length
SELECT f1 FROM t1 FORCE INDEX (`f1`) WHERE f1 = 'தமிழ்';
f1
தமிழ்
select @cluster_lookups;
@cluster_lookups
1
select @cluster_lookups_avoided;
@cluster_lookups_avoided
0
# Not eligible - record length longer than prefix length
SELECT f1 FROM t1 FORCE INDEX (`f1`) WHERE f1 like 'ggᵷ%';
f1
ggᵷg
select @cluster_lookups;
@cluster_lookups
2
select @cluster_lookups_avoided;
@cluster_lookups_avoided
0
# Not eligible - record length longer than prefix length
SELECT f1 FROM t1 FORCE INDEX (`f1`) WHERE f1 like '😊%';
f1
😊me
select @cluster_lookups;
@cluster_lookups
1
select @cluster_lookups_avoided;
@cluster_lookups_avoided
0
# Not eligible - record length longer than prefix length
SELECT f1 FROM t1 FORCE INDEX (`f1`) WHERE f1 = 'ls¢';
f1
ls¢
select @cluster_lookups;
@cluster_lookups
1
select @cluster_lookups_avoided;
@cluster_lookups_avoided
0
# Eligible - record length shorter than prefix length
SELECT f1 FROM t1 FORCE INDEX(`f1`) WHERE f1 like '¢¢%';
f1
¢¢
select @cluster_lookups;
@cluster_lookups
1
select @cluster_lookups_avoided;
@cluster_lookups_avoided
1
# Eligible - record length shorter than prefix length
SELECT f1 FROM t1 FORCE INDEX (`f1`) WHERE f1 like '🐱🌑%';
f1
🐱🌑
select @cluster_lookups;
@cluster_lookups
2
select @cluster_lookups_avoided;
@cluster_lookups_avoided
0
# Eligible - record length is shorter than prefix length
SELECT f1 FROM t1 FORCE INDEX (`f1`) WHERE f1 like '🌑%';
f1
🌑
select @cluster_lookups;
@cluster_lookups
0
select @cluster_lookups_avoided;
@cluster_lookups_avoided
2
# Eligible - record length is shorter than prefix length
SELECT f1 FROM t1 FORCE INDEX (`f1`) WHERE f1 like '🌒%';
f1
🌒
select @cluster_lookups;
@cluster_lookups
1
select @cluster_lookups_avoided;
@cluster_lookups_avoided
1
DROP TABLE t1;
CREATE TABLE t1(
col1 INT,
col2 BLOB DEFAULT NULL,
INDEX `idx1`(col2(4), col1))ENGINE=INNODB;
INSERT INTO t1 VALUES (2, 'test'), (3, repeat('test1', 2000));
INSERT INTO t1(col1) VALUES(1);
# Eligible - record length is shorter than prefix length
SELECT col1 FROM t1 FORCE INDEX (`idx1`) WHERE col2 is NULL;
col1
1
select @cluster_lookups;
@cluster_lookups
0
select @cluster_lookups_avoided;
@cluster_lookups_avoided
1
# Not eligible - record length longer than prefix index
SELECT col1 FROM t1 FORCE INDEX (`idx1`) WHERE col2 like 'test1%';
col1
3
select @cluster_lookups;
@cluster_lookups
2
select @cluster_lookups_avoided;
@cluster_lookups_avoided
0
DROP TABLE t1;
set global innodb_prefix_index_cluster_optimization = OFF;