SQL 带 LIKE 的参数 ?% 强制使用索引
SQL parameters with LIKE ?% force use index
当我只想在像 foo% 这样的词后使用通配符搜索时,我如何在使用 LIKE(也许是更好的解决方案?)和参数绑定时强制使用索引?请参阅使用和不使用参数绑定的示例。我想防止参数示例中的tableScan。
我正在使用带有 H2 数据库的 SpringBoot 应用程序。
不带参数的查询:
SELECT *
FROM (SELECT resource_id FROM SEARCH_TABLE_874 WHERE word LIKE 'su%')
GROUP BY resource_id ORDER BY COUNT (*) DESC LIMIT 100
执行计划:
SELECT
_1.RESOURCE_ID
FROM (
SELECT
RESOURCE_ID
FROM PUBLIC.SEARCH_TABLE_874
WHERE WORD LIKE 'su%'
) _1
/* SELECT
RESOURCE_ID
FROM PUBLIC.SEARCH_TABLE_874
/++ PUBLIC.IDX_SEARCH_TABLE_874_WORD: WORD >= 'su'
AND WORD < 'sv'
++/
WHERE WORD LIKE 'su%'
*/
GROUP BY RESOURCE_ID
ORDER BY =COUNT(*) DESC
LIMIT 100`
带参数查询:
`SELECT * FROM (SELECT resource_id FROM SEARCH_TABLE_874 WHERE word LIKE :param) GROUP BY resource_id ORDER BY COUNT (*) DESC LIMIT 100`
执行计划:
`SELECT
_10.RESOURCE_ID
FROM (
SELECT
RESOURCE_ID
FROM PUBLIC.SEARCH_TABLE_874
WHERE WORD LIKE CONCAT(?1, '%')
) _10
/* SELECT
RESOURCE_ID
FROM PUBLIC.SEARCH_TABLE_874
/++ PUBLIC.SEARCH_TABLE_874.tableScan ++/
WHERE WORD LIKE CONCAT(?1, '%')
*/
GROUP BY RESOURCE_ID
ORDER BY =COUNT(*) DESC
LIMIT 100
查询来源的更多详细信息:
这是一个搜索引擎。
Query被代码生成为String,然后像String一样执行:
Query query = session.createNativeQuery(queryString);
query.setParameter("param", "foo%");
query.getFirstResult()
对于执行计划,我在查询前写了 EXPLAIN。该结构是因为可以通过 UNION 进行许多子选择。
解决方案在不带参数的查询的执行计划中。我现在使用 WORD >= 'foo' AND WORD < 'fop'
而不是 LIKE 'foo%
。这样数据库就可以使用索引了。
当我只想在像 foo% 这样的词后使用通配符搜索时,我如何在使用 LIKE(也许是更好的解决方案?)和参数绑定时强制使用索引?请参阅使用和不使用参数绑定的示例。我想防止参数示例中的tableScan。
我正在使用带有 H2 数据库的 SpringBoot 应用程序。
不带参数的查询:
SELECT *
FROM (SELECT resource_id FROM SEARCH_TABLE_874 WHERE word LIKE 'su%')
GROUP BY resource_id ORDER BY COUNT (*) DESC LIMIT 100
执行计划:
SELECT
_1.RESOURCE_ID
FROM (
SELECT
RESOURCE_ID
FROM PUBLIC.SEARCH_TABLE_874
WHERE WORD LIKE 'su%'
) _1
/* SELECT
RESOURCE_ID
FROM PUBLIC.SEARCH_TABLE_874
/++ PUBLIC.IDX_SEARCH_TABLE_874_WORD: WORD >= 'su'
AND WORD < 'sv'
++/
WHERE WORD LIKE 'su%'
*/
GROUP BY RESOURCE_ID
ORDER BY =COUNT(*) DESC
LIMIT 100`
带参数查询:
`SELECT * FROM (SELECT resource_id FROM SEARCH_TABLE_874 WHERE word LIKE :param) GROUP BY resource_id ORDER BY COUNT (*) DESC LIMIT 100`
执行计划:
`SELECT
_10.RESOURCE_ID
FROM (
SELECT
RESOURCE_ID
FROM PUBLIC.SEARCH_TABLE_874
WHERE WORD LIKE CONCAT(?1, '%')
) _10
/* SELECT
RESOURCE_ID
FROM PUBLIC.SEARCH_TABLE_874
/++ PUBLIC.SEARCH_TABLE_874.tableScan ++/
WHERE WORD LIKE CONCAT(?1, '%')
*/
GROUP BY RESOURCE_ID
ORDER BY =COUNT(*) DESC
LIMIT 100
查询来源的更多详细信息:
这是一个搜索引擎。
Query被代码生成为String,然后像String一样执行:
Query query = session.createNativeQuery(queryString);
query.setParameter("param", "foo%");
query.getFirstResult()
对于执行计划,我在查询前写了 EXPLAIN。该结构是因为可以通过 UNION 进行许多子选择。
解决方案在不带参数的查询的执行计划中。我现在使用 WORD >= 'foo' AND WORD < 'fop'
而不是 LIKE 'foo%
。这样数据库就可以使用索引了。