{"record":{"id":"be95389abd2d8a51","repo":"baomidou/mybatis-plus","slug":"sql-sql-table","errorCode":null,"errorMessage":"非法SQL，SQL未使用到索引, table:","messagePattern":"非法SQL，SQL未使用到索引, table:","errorType":"exception","errorClass":"MybatisPlusException","httpStatus":null,"severity":"error","filePath":"mybatis-plus-jsqlparser-support/mybatis-plus-jsqlparser/src/main/java/com/baomidou/mybatisplus/extension/plugins/inner/IllegalSQLInnerInterceptor.java","lineNumber":248,"sourceCode":"    private void validUseIndex(Table table, String columnName, Connection connection) {\n        //是否使用索引\n        boolean useIndexFlag = false;\n        if (StringUtils.isNotBlank(columnName)) {\n            //表存在的索引\n            String dbName = table.getSchemaName();\n            String tableName = table.getName();\n            String catalogName = table.getCatalogName();\n            columnName = SqlParserUtils.removeWrapperSymbol(columnName);\n            List<IndexInfo> indexInfos = getIndexInfos(null, catalogName, dbName, tableName, connection);\n            for (IndexInfo indexInfo : indexInfos) {\n                if (indexInfo.getColumnName().equalsIgnoreCase(columnName)) {\n                    useIndexFlag = true;\n                    break;\n                }\n            }\n        }\n        if (!useIndexFlag) {\n            throw new MybatisPlusException(\"非法SQL，SQL未使用到索引, table:\" + table.getName() + \", columnName:\" + columnName);\n        }\n    }\n\n    /**\n     * 验证where条件的字段，是否有not、or等等，并且where的第一个字段，必须使用索引\n     *\n     * @param expression ignore\n     * @param table      ignore\n     * @param connection ignore\n     */\n    private void validWhere(Expression expression, Table table, Connection connection) {\n        validWhere(expression, table, null, connection);\n    }\n\n    /**\n     * 验证where条件的字段，是否有not、or等等，并且where的第一个字段，必须使用索引\n     *\n     * @param expression ignore","sourceCodeStart":230,"sourceCodeEnd":266,"githubUrl":"https://github.com/baomidou/mybatis-plus/blob/bf67d907478c724120bf76292da54abf9e73c2b3/mybatis-plus-jsqlparser-support/mybatis-plus-jsqlparser/src/main/java/com/baomidou/mybatisplus/extension/plugins/inner/IllegalSQLInnerInterceptor.java#L230-L266","documentation":"Non-5.0 variant of the index check: IllegalSQLInnerInterceptor collects IndexInfo via getIndexInfos(null, catalogName, dbName, tableName, connection) and, when the leading WHERE column matches no indexed column name, throws 'SQL未使用到索引' naming table and column. The leading predicate must be covered by an index visible through JDBC DatabaseMetaData.","triggerScenarios":"Registering the interceptor with index validation enabled and running a query whose first WHERE column is unindexed; also when dbName/catalog passed to metadata lookup is wrong so index lookup returns an empty list and every column 'fails'.","commonSituations":"Schema drift between environments (index exists in prod, not in the dev DB the app connects to); column name case mismatch with JDBC metadata; table referenced via alias or schema prefix confusing the lookup; teams enabling the check before back-filling indexes.","solutions":["Create the missing index on the leading WHERE column","Reorder predicates so an indexed column leads the WHERE expression","Confirm dbName/catalog in the JDBC URL and table reference match where the index lives (SHOW INDEX FROM t)","Temporarily disable the index check or interceptor for statements where a scan is intentional"],"exampleFix":"-- before: interceptor rejects WHERE tenant_id = ? on t_order\nclasspath: schema.sql\nCREATE INDEX idx_t_order_tenant_id ON t_order(tenant_id);\n-- after: same query passes validation","handlingStrategy":"try-catch","validationCode":"// Assert the leading WHERE column is indexed before enabling/executing\ntry (Connection c = dataSource.getConnection();\n     ResultSet rs = c.getMetaData().getIndexInfo(null, c.getCatalog(), \"t_order\", false, false)) {\n    boolean found = false;\n    while (rs.next()) {\n        if (\"tenant_id\".equalsIgnoreCase(rs.getString(\"COLUMN_NAME\"))) { found = true; break; }\n    }\n    if (!found) throw new IllegalStateException(\"Missing index on t_order.tenant_id\");\n}","typeGuard":null,"tryCatchPattern":"try {\n    return orderMapper.byTenant(tenantId);\n} catch (MybatisPlusException e) {\n    if (e.getMessage() != null && e.getMessage().contains(\"未使用到索引\")) {\n        throw new IllegalStateException(\"Leading WHERE column unindexed — fix schema or reorder predicate\", e);\n    }\n    throw e;\n}","preventionTips":["Create indexes for leading filter columns in the same migration that enables the interceptor","Verify dbName/catalog in JDBC URLs so metadata lookups find your indexes","Smoke-test interceptor-enabled queries against every environment's schema"],"tags":["mybatis-plus","index","ddl","performance","interceptor"],"backgroundTag":null,"analyzedSha":"bf67d907478c724120bf76292da54abf9e73c2b3","analyzedAt":"2026-08-14T15:17:09.543Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}