When you use Lindorm SQL to query wide table data or create an index, you might encounter errors or unexpected query performance. This topic describes common issues and solutions for using Lindorm SQL.
The common issues described in this topic apply only to LindormTable.
How do I resolve or avoid inefficient queries?
What is an inefficient query and what are its characteristics?
If a query statement includes a filter condition that cannot effectively use an existing primary key or index, the query must perform a full table scan. This type of query is considered inefficient.
If LindormTable returns the error This query may be a full table scan and thus may have unpredictable performance when you execute a query, the query is inefficient. For example, assume that the composite primary key of the `test` table consists of three columns: `p1`, `p2`, and `p3`. The `p1` column is the first column of the primary key. Consider the query SELECT * FROM test WHERE p2=10;. In this case, the query condition does not include the first primary key column `p1`. Therefore, the query statement is considered inefficient.
By default, Lindorm detects and blocks inefficient queries because these queries can degrade the performance and stability of the database.
Why does a query trigger an inefficient query exception even if the WHERE clause contains a primary key column or an index column?
The matching rules for primary keys and secondary indexes in LindormTable are similar to those for composite indexes in MySQL. They all follow the leftmost prefix rule. This means that for a composite primary key or index with multiple columns, the system matches the columns in the query condition against the key columns one by one, starting from the first (leftmost) column. If the query condition does not include the first column of the primary key or index key, the query does not hit the primary key or secondary index. This results in an inefficient query.
For example, assume that the primary key of the `test` table consists of three columns: `p1`, `p2`, and `p3`. The `p1` column is the first column of the primary key. According to the leftmost prefix rule, the system starts matching from the `p1` column when querying data. If the query condition does not include the `p1` column, such as in SELECT * FROM test WHERE p2<30;, the system cannot match the first primary key column `p1`. The query does not hit the primary key, and the system instead scans the entire table to satisfy the query condition p2<30.
How can I avoid inefficient queries?
You can use the following methods to avoid inefficient queries in your applications:
Optimize the query conditions. Add the primary key of the table to the WHERE clause, or ensure that the columns in the query condition follow the leftmost prefix rule.
Modify the primary key design of the table to avoid large queries. For more information, see How to design a primary key for a wide table.
Create a secondary index for the table. For more information, see Secondary indexes.
To perform multidimensional searches on multiple columns of a table, create a search index for the table to accelerate queries. For more information, see Search indexes.
Add the
/*+ _l_allow_filtering_ */HINT to the query statement to force LindormTable to execute the inefficient query. For example:SELECT /*+ _l_allow_filtering_ */ * FROM dt WHERE nonPK=100;.ImportantForcing the execution of inefficient queries can pose risks to performance and stability. Use this method with caution.
Why does a GROUP BY query fail with the error The diff group keys of subPlan is over lindorm.aggregate.subplan.groupby.keys.limit=..., it may cost a lot memory so we shutdown this SubPlan?
Cause:
The number of groups created by the GROUP BY operation is too large. This operation can consume excessive memory resources and increase the instance load. Therefore, LindormTable limits queries that produce many groups in the result set.
Solution:
Add filter conditions to the query statement to reduce the final number of groups.
Contact Lindorm technical support (DingTalk ID: s0s3eg3) to increase the threshold for the number of groups.
ImportantIncreasing the threshold for the number of groups might affect the stability of the instance.
For multidimensional query scenarios, we recommend using a search index. For more information, see Introduction to search indexes.
Why does a SELECT * query on a table with dynamic columns enabled fail with the error Limit of this select statement is not set or exceeds config when select all columns from table with property DYNAMIC_COLUMNS=true?
Cause:
A table with dynamic columns enabled may contain many dynamic columns, and its schema is not fixed. If you perform a full table scan on such a table, this can cause high I/O consumption and increase the instance load. To prevent high load situations, LindormTable places restrictions on query statements for tables with dynamic columns.
Solution:
Add a LIMIT clause to the SELECT statement to limit the number of results returned. For example: SELECT * FROM test LIMIT 10;.
Why does creating a secondary index fail with the error Executing job number exceed, max job number = 8?
Cause:
An instance allows a maximum of eight secondary index build tasks to run concurrently. If eight build tasks are already running, any new attempt to create a secondary index will fail with this error.
Solution:
Avoid creating many secondary indexes simultaneously. To create many indexes, contact Lindorm technical support (DingTalk ID: s0s3eg3).
After deleting a column in LindormTable, why does re-adding a column with the same name fail with the error column is under deleting?
Cause:
To prevent dirty data issues caused by factors such as data types, LindormTable asynchronously cleans up the column's data from memory, hot storage, and cold storage after you delete the column. The system does not allow you to add a new column with the same name until the cleanup process is complete.
Solution:
The data cleanup is performed by the system and can take a long time. You can use the following methods to accelerate the cleanup process. After the cleanup is complete, you can add the column with the same name again.
Assume that the table from which the column was deleted is named dt:
-- Execute the FLUSH operation to force residual data in memory to be flushed to the storage medium.
ALTER TABLE dt FLUSH;
-- Execute the COMPACTION operation to merge and delete data.
ALTER TABLE dt COMPACT;The
FLUSHsyntax is supported starting from SQL engine version 2.7.1. To view your SQL engine version, see SQL version guide.The
FLUSHandCOMPACToperations are asynchronous. A successful execution of the statement does not mean the data cleanup is complete. The cleanup process may take some time to complete.Running the
COMPACToperation on a table with a large data volume consumes significant system resources. Do not run this operation during peak business hours.
After creating a secondary index, why does writing data fail with the error Performing put operations with User-Defined-Timestamp in indexed column on MULTABLE_LATEST table is unsupported?
Cause:
If you explicitly specify a custom timestamp when writing data (for example, using the /*+ _l_ts */ HINT in an UPSERT statement), the mutability of both the primary table and the secondary index table must be MULTABLE_ALL. However, for performance reasons, Lindorm defaults the mutability of the primary and index tables to MULTABLE_LATEST. Creating and enabling a secondary index with this configuration triggers a mutability constraint violation, which causes the error.
Solution:
The value of the MUTABILITY parameter cannot be modified after an index table is created. You must first delete the original secondary index.
Delete the original secondary index from the primary table.
-- Disable the original secondary index. ALTER INDEX IF EXISTS <original_secondary_index_name> ON <primary_table_name> DISABLED; -- Delete the original secondary index. DROP INDEX IF EXISTS <original_secondary_index_name> ON <primary_table_name>;For more information about the
DROP INDEXsyntax, see Delete a secondary index.Change the value of the MUTABILITY property of the primary table to
MUTABLE_ALL.ALTER TABLE IF EXISTS <primary_table_name> SET MUTABILITY='MUTABLE_ALL';Create a new secondary index and write data. For more information about the syntax for creating a secondary index, see CREATE INDEX.
NoteFor more information about how to write data with a custom timestamp, see Use HINTs to set timestamps for multi-version data management.
For more information about the relationship between secondary index mutability constraints and custom timestamps, see Update an index with a custom timestamp.
Why does an SQL query fail with the error Code grows beyond 64 KB?
Cause:
The Lindorm SQL engine uses Just-In-Time (JIT) compilation to execute queries. It dynamically generates bytecode from the physical plan of a query and then compiles and executes it. The Code grows beyond 64KB error indicates that the size of the bytecode for the generated method exceeds the limit allowed by the Java Virtual Machine (JVM). This can happen if a predicate in the SQL query statement is too long or complex, resulting in bytecode that is too large to be executed.
Solution:
Modify the SQL statement to simplify the relevant predicate expressions.
Why does an SQL query fail with the error The estimated memory used by the query exceeds the maximum limit?
Cause:
The SQL engine often consumes large amounts of memory resources when it processes result sets returned from the storage engine, such as during aggregation, sorting, or deduplication. Lindorm SQL is designed for online business scenarios where many queries may run concurrently. To ensure query efficiency in high-concurrency scenarios, the system limits the memory usage of a single query. The current default limit is 8 MB. If this limit is exceeded, a memory overflow exception is triggered.
Solution:
Optimize the query statement. You can push down operators, such as aggregation and sorting, to the storage engine using indexes. You can also optimize filter conditions to reduce the amount of data that the SQL engine needs to process.
NoteYou can check the execution plan to see if operators such as aggregation and sorting are pushed down to the storage engine or executed by the SQL engine. For more information, see Interpret an execution plan.
Adjust the `QUERY_MAX_MEM` memory limit threshold. After you fully evaluate the query throughput, you can adjust the `QUERY_MAX_MEM` configuration item using the ALTER SYSTEM statement. For example:
ALTER SYSTEM SET QUERY_MAX_MEM = 8388608;. If your SQL engine version is earlier than 2.9.6.0, contact Lindorm technical support (DingTalk ID: s0s3eg3) to increase the memory limit threshold.ImportantIf an online application has high query concurrency, increasing this memory limit threshold can increase the memory load on Lindorm. This, in turn, can trigger behaviors such as a forced Full GC and reduce the responsiveness of the entire cluster. Therefore, perform a thorough evaluation before you increase this memory limit. You can retrieve the current value of
QUERY_MAX_MEMusing the SHOW VARIABLES statement.