【发布时间】:2018-12-20 14:02:46
【问题描述】:
我正在开发一个应用程序,我正在使用 Spring Data JPA 进行数据库操作。
我正在实现一个使用搜索栏查找朋友的功能。它应该工作的方式是,当您输入一些字符时,会在数据库中执行搜索以查找并显示与字符匹配的 10 个用户(名字以它开头,姓氏以它开头,它也应该如果有人输入全名,则工作)。
我已经编写了代码,它的工作方式如下:
@Query(nativeQuery = true,
value="SELECT * FROM users u WHERE (" +
"UPPER(first_name) like CONCAT(UPPER(:query),'%') OR " +
"UPPER(last_name) like CONCAT(UPPER(:query),'%') OR " +
"UPPER(CONCAT(first_name,' ', last_name)) like CONCAT(UPPER(:query),'%')" +
") LIMIT 10")
List<User> findByQueryLikeName(@Param("query") String query);
但是,当我查看此查询时,它确实似乎不是最好的性能。我对 sql 性能了解不多,但我认为这是因为它结合了 3 个 where 语句和一个 OR 运算符,并且还大量使用了 UPPER 和 CONCAT 等一些函数。我正在使用 PostgreSQL。
您能否评估一下这种查询是否会在大量记录上表现良好?你能试着解释一下为什么/为什么不?你有什么改进的小窍门吗?
非常感谢!
【问题讨论】:
-
名字和姓氏的连接将排除您的 SQL 使用索引的任何机会。但是,即使在此之前,将列包装在
UPPER中也可能会导致无法使用索引。 -
@TimBiegeleisen:除非您使用该表达式创建索引。
-
Postgres' full text search 可能值得一看。或trigram indexes
-
是的,你需要三个索引,每个表达式一个,然后你可以期待
BitmapOr。这是一个相当糟糕的查询。 -
upper 的要点是使搜索不区分大小写。连接的目的是启用名字和姓氏的搜索。例如,对于亚当·史密斯,我想匹配诸如“亚当·斯米”之类的查询。您能否建议我如何改进我的 SQL 查询,以便我可以使用索引并仍然拥有这些功能?
标签: sql postgresql performance spring-data-jpa