Important

The SingleStore 9.1 release candidate (RC) gives you the opportunity to preview, evaluate, and provide feedback on new and upcoming features prior to their general availability. In the interim, SingleStore 9.0 is recommended for production workloads, which can later be upgraded to SingleStore 9.1.

Migrating and Troubleshooting Collations

As of SingleStore version 9.0, the default collation for new clusters is utf8mb4_bin. Existing clusters that are upgraded to SingleStore version 9.0 continue to use their current collation unless it is explicitly changed.

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_set_server is set to the corresponding character set. These collation_* variables must be set globally. If any of these variables are set in a session to a value other than the current global setting, SingleStore returns an error.

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. It changes the default collation used by new sessions and objects that inherit the current default. Existing metadata remains unchanged until the objects are altered or rebuilt.

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_name
    FROM information_schema.columns
    WHERE 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_general_ci to utf8mb4_bin, rewrite the application queries that rely on case-insensitive behavior.

  • 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. Mismatched data types or collations can cause warnings in the query EXPLAIN and prevent SingleStore from using an index match. Such comparisons may involve unsafe conversions, degrade performance, and prevent index matching, which can lead to high CPU usage. For example, comparing an indexed column to a value or expression that resolves to a different collation can force a scan instead of an index lookup, i.e., the query optimizer may not be able to efficiently use the index.

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 COLLATE clauses 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_cs
FROM grades
GROUP BY 1
ORDER BY 1;
+-------------+
| lastname_cs |
+-------------+
| Browning    |
| Williams    |
| williams    |
+-------------+

String Literal Override

Assuming the session default is utf8mb4_bin, 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 grades1
WHERE lastname = 'williams' COLLATE utf8mb4_general_ci;
+------------+----------+
| student_id | lastname |
+------------+----------+
|          2 | Williams |
|          1 | williams |
+------------+----------+

Note the ColumnStoreFilter ... index in the following EXPLAIN output that indicates that the predicate used an index:

EXPLAIN SELECT * FROM grades1
WHERE 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_bin) and cause a mismatch. Notice the warning in the EXPLAIN output:

EXPLAIN SELECT * FROM grades1
WHERE 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. For example:

SELECT * FROM sets
WHERE 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:

  1. 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_name
    FROM information_schema.columns
    WHERE collation_name = 'utf8mb4_general_ci' AND table_schema NOT IN ('information_schema');
  2. Change the collation: Change the default collation for the cluster.

    SET CLUSTER collation_server = 'utf8mb4_bin';
  3. Reset the connections: Run the FLUSH CONNECTION POOLS command on each aggregator in the cluster to close all the open connections and the idle pooled connections.

    FLUSH CONNECTION POOLS;
  4. 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 t1
      MODIFY 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 t1
      MODIFY 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 rows
      SELECT COUNT(*) AS mismatched_rows
      FROM towns
      WHERE town_name != town_name_2;
      -- Review mismatched rows
      SELECT id, town_name, town_name_2
      FROM towns
      WHERE 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.

  5. Test existing queries and applications: Re-run the existing queries with EXPLAIN and 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:

Was this article helpful?

Verification instructions

Note: You must install cosign to verify the authenticity of the SingleStore file.

Use the following steps to verify the authenticity of singlestoredb-server, singlestoredb-toolbox, singlestoredb-studio, and singlestore-client SingleStore files that have been downloaded.

You may perform the following steps on any computer that can run cosign, such as the main deployment host of the cluster.

  1. (Optional) Run the following command to view the associated signature files.

    curl undefined
  2. Download the signature file from the SingleStore release server.

    • Option 1: Click the Download Signature button next to the SingleStore file.

    • Option 2: Copy and paste the following URL into the address bar of your browser and save the signature file.

    • Option 3: Run the following command to download the signature file.

      curl -O undefined
  3. After the signature file has been downloaded, run the following command to verify the authenticity of the SingleStore file.

    echo -n undefined |
    cosign verify-blob --certificate-oidc-issuer https://oidc.eks.us-east-1.amazonaws.com/id/CCDCDBA1379A5596AB5B2E46DCA385BC \
    --certificate-identity https://kubernetes.io/namespaces/freya-production/serviceaccounts/job-worker \
    --bundle undefined \
    --new-bundle-format -
    Verified OK

Try Out This Notebook to See What’s Possible in SingleStore

Get access to other groundbreaking datasets and engage with our community for expert advice.