本文目录导读:

针对Java模糊查询(LIKE)的优化,以下是几种有效的提速方案,按推荐优先级排序:
数据库索引优化(最基础)
前缀模糊查询
-- 使用普通B-Tree索引即可 CREATE INDEX idx_name ON users(name); -- 查询必须使用前缀匹配 SELECT * FROM users WHERE name LIKE '张%';
全文索引(推荐)
// MySQL全文索引查询 @Query(value = "SELECT * FROM articles WHERE MATCH(title, content) AGAINST(?1 IN BOOLEAN MODE)", nativeQuery = true) List<Article> searchByFullText(String keyword);
-- 创建全文索引
CREATE FULLTEXT INDEX idx_fulltext ON articles(title, content);
-- 查询语法
SELECT * FROM articles WHERE MATCH(title, content) AGAINST('+关键词*' IN BOOLEAN MODE);
Elasticsearch搜索引擎(高性能方案)
基础配置
// 1. 添加依赖
implementation 'org.springframework.boot:spring-boot-starter-data-elasticsearch'
// 2. 实体映射
@Document(indexName = "users")
public class UserDocument {
@Id
private Long id;
@Field(type = FieldType.Text, analyzer = "ik_max_word")
private String name;
@Field(type = FieldType.Text, analyzer = "ik_smart")
private String description;
}
// 3. Repository
public interface UserSearchRepository extends ElasticsearchRepository<UserDocument, Long> {
List<UserDocument> findByNameContaining(String keyword);
}
// 4. 服务层查询
@Service
public class SearchService {
@Autowired
private UserSearchRepository searchRepository;
public List<UserDocument> searchByName(String keyword) {
return searchRepository.findByNameContaining(keyword);
}
}
高级查询(支持模糊、高亮)
public class ElasticsearchService {
public List<UserDocument> fuzzySearch(String keyword) {
// 构建模糊查询
NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
// 模糊查询
queryBuilder.withQuery(QueryBuilders.fuzzyQuery("name", keyword)
.fuzziness(Fuzziness.AUTO));
// 或通配符查询
queryBuilder.withQuery(QueryBuilders.wildcardQuery("name", "*" + keyword + "*"));
// 高亮显示
HighlightBuilder highlightBuilder = new HighlightBuilder();
highlightBuilder.field("name");
queryBuilder.withHighlightBuilder(highlightBuilder);
return elasticsearchTemplate.queryForPage(queryBuilder.build(), UserDocument.class).getContent();
}
}
分库分表+中间表策略
创建搜索专用表
-- 1. 创建搜索中间表
CREATE TABLE user_search_index (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
user_id BIGINT,
search_text VARCHAR(500),
INDEX idx_search_text(search_text)
) ENGINE=InnoDB;
-- 2. 数据同步(定时任务或触发器)
INSERT INTO user_search_index(user_id, search_text)
SELECT id, CONCAT(name, ',', email, ',', phone) FROM users;
-- 3. 搜索查询
SELECT u.* FROM users u
INNER JOIN user_search_index si ON u.id = si.user_id
WHERE si.search_text LIKE '%关键词%'
LIMIT 20;
缓存策略(Redis)
缓存热点搜索词
@Service
public class SearchCacheService {
@Autowired
private RedisTemplate<String, Object> redisTemplate;
private static final String SEARCH_CACHE_PREFIX = "search:keyword:";
private static final long CACHE_TTL = 300; // 5分钟
public List<User> searchWithCache(String keyword) {
String cacheKey = SEARCH_CACHE_PREFIX + keyword;
// 1. 尝试从缓存获取
List<User> cachedResult = (List<User>) redisTemplate.opsForValue().get(cacheKey);
if (cachedResult != null) {
return cachedResult;
}
// 2. 缓存未命中,查询数据库
List<User> result = userRepository.findByNameContaining(keyword);
// 3. 异步写入缓存
CompletableFuture.runAsync(() -> {
redisTemplate.opsForValue().set(cacheKey, result, CACHE_TTL, TimeUnit.SECONDS);
});
return result;
}
}
SQL优化技巧
强制索引与查询优化
@Repository
public class UserRepositoryImpl {
@PersistenceContext
private EntityManager entityManager;
public List<User> searchByKeyword(String keyword) {
// 1. 使用HINT强制索引
Query query = entityManager.createNativeQuery(
"SELECT * FROM users USE INDEX(idx_name) WHERE name LIKE ?1", User.class);
query.setParameter(1, keyword + "%"); // 前缀查询
// 2. 限制返回行数
query.setMaxResults(100);
return query.getResultList();
}
// 3. 分批查询,避免大结果集
public List<User> searchByBatch(String keyword, int batchSize) {
List<User> results = new ArrayList<>();
int offset = 0;
List<User> batch;
do {
batch = entityManager.createNativeQuery(
"SELECT * FROM users WHERE name LIKE ?1 LIMIT ?2 OFFSET ?3", User.class)
.setParameter(1, "%" + keyword + "%")
.setParameter(2, batchSize)
.setParameter(3, offset)
.getResultList();
results.addAll(batch);
offset += batchSize;
} while (batch.size() == batchSize);
return results;
}
}
实际案例:综合优化方案
// 完整优化方案
@Service
@Slf4j
public class OptimizedSearchService {
@Autowired
private UserRepository userRepository;
@Autowired
private UserSearchRepository searchRepository; // ES
@Autowired
private RedisTemplate<String, Object> redisTemplate;
/**
* 智能搜索:先ES,再数据库,最后缓存
*/
public Page<User> smartSearch(String keyword, int page, int size) {
long startTime = System.currentTimeMillis();
try {
// 1. 尝试ES搜索(高性能)
Page<UserDocument> esResults = searchRepository.search(
buildNativeSearchQuery(keyword),
PageRequest.of(page, size)
);
if (esResults.hasContent()) {
log.info("ES search took {}ms", System.currentTimeMillis() - startTime);
return convertToUserPage(esResults);
}
} catch (Exception e) {
log.warn("ES search failed, falling back to database", e);
}
// 2. ES失败时使用数据库+缓存
String cacheKey = "search:" + keyword + ":" + page + ":" + size;
// 从缓存获取
Page<User> cached = (Page<User>) redisTemplate.opsForValue().get(cacheKey);
if (cached != null) {
log.info("Cache hit for keyword: {}", keyword);
return cached;
}
// 3. 数据库查询(使用优化索引)
Page<User> dbResults = userRepository.findByNameStartingWith(
keyword,
PageRequest.of(page, size)
);
// 4. 写入缓存(异步)
if (dbResults.hasContent()) {
CompletableFuture.runAsync(() -> {
redisTemplate.opsForValue().set(cacheKey, dbResults, 300, TimeUnit.SECONDS);
});
}
log.info("Database search took {}ms", System.currentTimeMillis() - startTime);
return dbResults;
}
}
优化对比表
| 方案 | 性能提升 | 复杂度 | 适用场景 |
|---|---|---|---|
| 索引优化 | 2-10倍 | 低 | 前缀查询 |
| 全文索引 | 5-20倍 | 中 | 全文搜索 |
| Elasticsearch | 10-100倍 | 高 | 大规模搜索 |
| 缓存策略 | 3-10倍 | 中 | 热点数据 |
| 分表策略 | 3-5倍 | 高 | 超大数据表 |
关键优化建议
- 避免使用
%keyword%:这种查询无法使用索引 - 限制结果集大小:使用
LIMIT或分页 - 使用覆盖索引:查询字段全部在索引中
- 考虑业务容忍度:对实时性要求不高的场景,可以接受秒级延迟
根据你的实际数据量和并发情况,选择最合适的优化方案,通常建议先尝试数据库索引优化,再考虑引入ES等重型方案。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播