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

Reply via email to