Migrating and Troubleshooting Collations
On this page
As of SingleStore version 9.utf8mb4_.
Impact of Changing collation_ server
When the default collation is changed for the cluster using any of the following engine variables:
-
collation_connection -
collation_database -
collation_server
the other two are automatically set to the same value and character_ is set to the corresponding character set.collation_ variables must be set globally.
After changing the collation for the cluster with SET CLUSTER or SET GLOBAL commands, run the FLUSH CONNECTION POOLS command on every aggregator in the cluster to apply the new collation.
Changing the collation does not automatically rewrite the collation of existing tables or columns.
Key considerations before changing the collation:
-
Check the currently active collation.
SELECT @@character_set_server, @@collation_server;SHOW VARIABLES LIKE 'collation%'; -
List the tables and columns that use an older (or specific) collation.
SELECT table_schema,table_name,column_name,character_set_name,collation_nameFROM information_schema.columnsWHERE table_schema NOT IN ('information_schema')ORDER BY table_schema, table_name, ordinal_position; -
Update the client application.
For example, when changing the collation from utf8mb4_togeneral_ ci utf8mb4_, rewrite the application queries that rely on case-insensitive behavior.bin -
Ensure that the client sessions and connection pools can be restarted after the change.
The new global collation configuration is not reliably applied until all the connection pools are flushed and sessions reconnect.
Collation Mismatch Behavior and Handling
A mismatch happens when a column, session default, or a literal or expression in a predicate condition (for example in the WHERE clause) does not resolve to the same effective data type or collation.EXPLAIN and prevent SingleStore from using an index match.
To prevent these issues, including query performance degradation, SingleStore recommends the following:
-
Match the collation of the literal or expression with the indexed column's collation instead of applying a different collation to the indexed column within the predicate.
-
Use explicit casts or
COLLATEclauses instead of relying on implicit conversions. -
Align the column collation with the expected application behavior.
Run a Query with a Different Collation or Character Set
To override the collation of expressions and literals in a query, use either of the following methods as applicable.
Refer to Character Set and Collation Override for related information.
Note
Changing the collation of the indexed column can prevent index matching.
Expression-Level Override
The following example uses expression-level override for case-sensitive sorting:
CREATE TABLE grades (student_id INT,lastname VARCHAR(25) COLLATE utf8mb4_general_ci);INSERT INTO grades VALUES(1, 'williams'),(2, 'Williams'),(3, 'Browning');SELECT lastname :> text COLLATE utf8mb4_bin AS lastname_csFROM gradesGROUP BY 1ORDER BY 1;
+-------------+
| lastname_cs |
+-------------+
| Browning |
| Williams |
| williams |
+-------------+String Literal Override
Assuming the session default is utf8mb4_, the following example explicitly specifies a case-insensitive collation for the expression.
CREATE TABLE grades1 (student_id INT,lastname VARCHAR(25) COLLATE utf8mb4_general_ci,KEY idx_lastname (lastname) USING HASH);INSERT INTO grades1 VALUES(1, 'williams'),(2, 'Williams'),(3, 'Browning');SELECT * FROM grades1WHERE lastname = 'williams' COLLATE utf8mb4_general_ci;
+------------+----------+
| student_id | lastname |
+------------+----------+
| 2 | Williams |
| 1 | williams |
+------------+----------+Note the ColumnStoreFilter . in the following EXPLAIN output that indicates that the predicate used an index:
EXPLAIN SELECT * FROM grades1WHERE lastname = 'williams' COLLATE utf8mb4_general_ci;
+---------------------------------------------------------------------------------------+
| EXPLAIN |
+---------------------------------------------------------------------------------------+
| Gather partitions:all alias:remote_0 parallelism_level:segment |
| Project [grades1.student_id, grades1.lastname] |
| ColumnStoreFilter [grades1.lastname = 'williams' COLLATE `utf8mb4_general_ci` index] |
| ColumnStoreScan demo.grades1, SORT KEY __UNORDERED () table_type:sharded_columnstore |
+---------------------------------------------------------------------------------------+Without the explicit collation override, the query may use the session's default collation (utf8mb4_) and cause a mismatch.EXPLAIN output:
EXPLAIN SELECT * FROM grades1WHERE lastname = 'williams';
+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| EXPLAIN |
+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| WARNING: Comparisons between mismatched datatypes which may involve unsafe datatype conversions and/or degrade performance. Consider changing the datatypes, or adding explicit typecasts. See https://docs.memsql.com/docs/mismatched-datatypes for more information. |
| |
| WARNING: Comparison between mismatched datatypes: (`grades1`.`lastname` = 'williams'). Types 'varchar(25) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL' vs 'longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL'. May degrade performance because an index match is not possible |
| |
| Gather partitions:all alias:remote_0 parallelism_level:segment |
| Project [grades1.student_id, grades1.lastname] |
| ColumnStoreFilter [grades1.lastname = 'williams'] |
| ColumnStoreScan demo.grades1, SORT KEY __UNORDERED () table_type:sharded_columnstore |
+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+Similarly, you can override the collation of the extracted JSON text.
SELECT * FROM setsWHERE sets.json_field::$x :> text COLLATE utf8mb4_bin = 'string1'AND sets.json_field::$y :> text COLLATE utf8mb4_general_ci = 'string2';
Migrate from utf8mb4_ general_ ci to utf8mb4_ bin Collation
SingleStore recommends performing the following actions, in order, to change the collation:
-
Inspect the current state: Check the current default collation for the cluster and identify the affected objects.
SELECT @@character_set_server, @@collation_server;SELECT table_schema,table_name,column_name,character_set_name,collation_nameFROM information_schema.columnsWHERE collation_name = 'utf8mb4_general_ci' AND table_schema NOT IN ('information_schema'); -
Change the collation: Change the default collation for the cluster.
SET CLUSTER collation_server = 'utf8mb4_bin'; -
Reset the connections: Run the
FLUSH CONNECTION POOLScommand on each aggregator in the cluster to close all the open connections and the idle pooled connections.FLUSH CONNECTION POOLS; -
Preserve existing column data and then migrate columns: Before changing the collation of an existing column, preserve its data until the migration has been validated.
Especially for columnstore tables, do not rename or drop the original column until copied values are successfully validated. -
Rowstore Tables
For rowstore tables, modify an existing string column directly.
ALTER TABLE t1MODIFY COLUMN col1 VARCHAR(128) COLLATE utf8mb4_bin;If the column has a secondary index, drop and recreate the index after changing the column collation.
For example: ALTER TABLE t1 DROP INDEX idx_c1;ALTER TABLE t1MODIFY COLUMN col1 VARCHAR(128) COLLATE utf8mb4_bin;ALTER TABLE t1 ADD INDEX idx_c1 (c1); -
Columnstore Tables
For columnstore tables, existing string columns cannot be modified in place.
Use an add-copy-swap-drop workflow, for example: ALTER TABLE towns ADD COLUMN town_name_2 VARCHAR(64) COLLATE utf8mb4_bin NOT NULL;UPDATE towns SET town_name_2 = town_name;After copying the data, validate the replacement column before continuing.
Do not drop or rename the original column until validation succeeds. For example: -- Check for mismatched rowsSELECT COUNT(*) AS mismatched_rowsFROM townsWHERE town_name != town_name_2;-- Review mismatched rowsSELECT id, town_name, town_name_2FROM townsWHERE town_name != town_name_2;After successful validation, swap the columns and drop the original column.
For example: ALTER TABLE towns CHANGE town_name town_name_to_delete;ALTER TABLE towns CHANGE town_name_2 town_name;ALTER TABLE towns DROP COLUMN town_name_to_delete;Re-create any indexes on the original column after swapping the columns.
Refer to ALTER TABLE to Modify Column Data Types, Sizes, and Collation for an example.
-
-
Test existing queries and applications: Re-run the existing queries with
EXPLAINand check plan warnings for mismatched data types or collations.Test existing workloads and applications and verify that everything is working as expected.
Risks of Migrating from utf8mb4_ general_ ci to utf8mb4_ bin Collation
-
Queries that previously relied on case-insensitive behavior may return different results.
-
Existing tables and columns are not rewritten automatically, which may lead to a mixed-collation environment immediately following a global collation change.
-
Query-time collation overrides or mismatched string literals may prevent index matching and reduce query performance.
-
Rowstore and columnstore migrations differ operationally; columnstore migrations are more invasive because existing string columns must be rebuilt.
Last modified: