UTF8 Collation UNICODE_CI_AI not working as expected causing poor performance
in database
-----------------------------------------------------------------------------------------
Key: CORE-5947
URL: http://tracker.firebirdsql.org/browse/CORE-5947
Project: Firebird Core
Issue Type: Bug
Components: Charsets/Collation
Affects Versions: 3.0.4
Environment: Windows x64 superserver, Linux x64 superserver
Reporter: Luis Forra
When migrating to utf8 with collation UNICODE_CI_AI I starting to note major
slowdown in performance, the problem is the full scan of the index when there
is more than one varchar in the index and is not unique
My original question in stackoverflow
https://stackoverflow.com/questions/52810369/firebird-3-0-4-unicode-ci-ai-index-problems
Example:
CREATE TABLE TEST_UNICODE (
S1 VARCHAR(10) CHARACTER SET UTF8 NOT NULL COLLATE UNICODE,
S2 VARCHAR(10) CHARACTER SET UTF8 NOT NULL COLLATE UNICODE
);
CREATE TABLE TEST_UNICODE_CI_AI (
S1 VARCHAR(10) CHARACTER SET UTF8 NOT NULL COLLATE UNICODE_CI_AI,
S2 VARCHAR(10) CHARACTER SET UTF8 NOT NULL COLLATE UNICODE_CI_AI
);
INSERT INTO TEST_UNICODE (S1, S2) VALUES ('A', 'A');
INSERT INTO TEST_UNICODE (S1, S2) VALUES ('A', 'B');
INSERT INTO TEST_UNICODE (S1, S2) VALUES ('B', 'A');
INSERT INTO TEST_UNICODE (S1, S2) VALUES ('B', 'B');
COMMIT WORK;
INSERT INTO TEST_UNICODE_CI_AI (S1, S2) VALUES ('A', 'A');
INSERT INTO TEST_UNICODE_CI_AI (S1, S2) VALUES ('A', 'B');
INSERT INTO TEST_UNICODE_CI_AI (S1, S2) VALUES ('B', 'A');
INSERT INTO TEST_UNICODE_CI_AI (S1, S2) VALUES ('B', 'B');
COMMIT WORK;
CREATE INDEX TEST_UNICODE ON TEST_UNICODE (S1, S2);
CREATE INDEX TEST_UNICODE_CI_AI ON TEST_UNICODE_CI_AI (S1, S2);
COMMIT WORK;
SELECT S1,S2 FROM test_unicode WHERE S1 = 'B' AND S2 = 'A'
UNION ALL
SELECT S1,S2 FROM test_unicode_ci_ai WHERE S1 = 'B' AND S2 = 'A'
The plan for this query is:
Select Expression
-> Union
-> Filter
-> Table "TEST_UNICODE" Access By ID
-> Bitmap
-> Index "TEST_UNICODE" Range Scan (full match)
-> Filter
-> Table "TEST_UNICODE_CI_AI" Access By ID
-> Bitmap
-> Index "TEST_UNICODE_CI_AI" Range Scan (partial match:
1/2)
I get 2 indexed reads with test_unicode_ci_ai and 1 indexed read with
test_unicode, with millions of records the problem escalates.
The workaround is to create the index unique by adding a numeric field in the
end.
The biggest problem is with foreign keys
example:
CREATE TABLE M_UNICODE (
S1 VARCHAR(10) CHARACTER SET UTF8 NOT NULL COLLATE UNICODE,
S2 VARCHAR(10) CHARACTER SET UTF8 NOT NULL COLLATE UNICODE
);
CREATE TABLE D_UNICODE (
S1 VARCHAR(10) CHARACTER SET UTF8 NOT NULL COLLATE UNICODE,
S2 VARCHAR(10) CHARACTER SET UTF8 NOT NULL COLLATE UNICODE
);
CREATE TABLE M_CI_AI (
S1 VARCHAR(10) CHARACTER SET UTF8 NOT NULL COLLATE UNICODE_CI_AI,
S2 VARCHAR(10) CHARACTER SET UTF8 NOT NULL COLLATE UNICODE_CI_AI
);
CREATE TABLE D_CI_AI (
S1 VARCHAR(10) CHARACTER SET UTF8 NOT NULL COLLATE UNICODE_CI_AI,
S2 VARCHAR(10) CHARACTER SET UTF8 NOT NULL COLLATE UNICODE_CI_AI
);
INSERT INTO M_UNICODE (S1, S2) VALUES ('A', 'A');
INSERT INTO M_UNICODE (S1, S2) VALUES ('A', 'B');
INSERT INTO M_CI_AI (S1, S2) VALUES ('A', 'A');
INSERT INTO M_CI_AI (S1, S2) VALUES ('A', 'B');
set term ^ ;
execute block
as
declare variable i bigint = 1000;
begin
while (i > 0) do
begin
insert into d_unicode (s1,s2) values ('A','A');
insert into d_ci_ai (s1,s2) values ('A','A');
i = i-1;
end
insert into d_unicode (s1,s2) values ('A','B');
insert into d_ci_ai (s1,s2) values ('A','B');
end^
set term ; ^
ALTER TABLE M_UNICODE ADD CONSTRAINT M_U PRIMARY KEY (S1, S2);
ALTER TABLE M_CI_AI ADD CONSTRAINT M_CI_AI PRIMARY KEY (S1, S2);
commit work;
ALTER TABLE D_UNICODE ADD CONSTRAINT D_U FOREIGN KEY (S1, S2) REFERENCES
M_UNICODE (S1, S2) ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE D_CI_AI ADD CONSTRAINT D_CI_AI FOREIGN KEY (S1, S2) REFERENCES
M_CI_AI (S1, S2) ON DELETE CASCADE ON UPDATE CASCADE;
commit work;
if i update the parent table with the collation UNICODE with:
update m_unicode set s2 = 'C' where s1 = 'A' and s2 = 'B'
it work as expected there is 2 indexed reads in the parent and child table
But if I update the parent table with the collation UNICODE_CI_AI with:
update m_ci_ai set s2 = 'C' where s1 = 'A' and s2 = 'B';
It reads all the index of the child table, in this case 2002 indexed reads.
In this case if I want to maintain the collation UNICDE_AI_CI I don't see any
workaround.
Adriano believes this bug is related to CORE-5940
Thank You
;
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators:
http://tracker.firebirdsql.org/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira
Firebird-Devel mailing list, web interface at
https://lists.sourceforge.net/lists/listinfo/firebird-devel