搜索历史该存哪些字段
用户每次输入并提交搜索词,就该记一条记录,核心字段必须有:
user_id(区分谁搜的)、
keyword(原始搜索词,注意去首尾空格)、
created_at(时间戳,用
DATETIME或
TIMESTAMP)。可选但强烈建议加
search_count(默认 1,后续可合并重复词)、
is_deleted(软删除标记,避免真删影响统计)。
别存
result_count或
response_time这类衍生数据——它们随业务逻辑变化,不该污染历史表结构。
建表语句怎么写才合理
用
ENGINE=InnoDB,主键用自增
id,但查询主要靠
user_id + created_at,所以要建联合索引。避免用
keyword做主键或唯一键——用户可能搜相同词多次,且长文本索引效率低。
CREATE TABLE `search_history` ( `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, `user_id` BIGINT UNSIGNED NOT NULL, `keyword` VARCHAR(255) NOT NULL, `search_count` INT UNSIGNED DEFAULT 1, `is_deleted` TINYINT UNSIGNED DEFAULT 0, `created_at` DATETIME DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`), INDEX `idx_user_time` (`user_id`, `created_at` DESC), INDEX `idx_user_keyword` (`user_id`, `keyword`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
注意:
VARCHAR(255)足够覆盖绝大多数搜索词;
utf8mb4支持 emoji 和生僻字;
DESC在索引里对分页查最新记录有帮助。
插入时怎么避免重复记录
不是所有重复都要合并——用户连续搜“苹果”两次,是两条独立行为。但若想支持「合并同类项」(比如展示“苹果(3次)”),得用
INSERT ... ON DUPLICATE KEY UPDATE,前提是
user_id + keyword有唯一约束:
先加唯一索引:
ALTER TABLE search_history ADD UNIQUE KEY `uk_user_keyword` (`user_id`, `keyword`);
再执行插入:
INSERT INTO search_history (user_id, keyword, search_count, created_at) VALUES (123, 'mysql优化', 1, NOW()) ON DUPLICATE KEY UPDATE search_count = search_count + 1, created_at = NOW();
⚠️ 注意:加唯一索引后,如果业务允许同一用户反复搜相同词但保留多条记录(如分析搜索频次分布),就别用这个方案,改用普通
INSERT+ 后续聚合查询。
查最近 10 条怎么写不出错
直接
ORDER BY created_at DESC LIMIT 10是常见写法,但要注意两点: 必须走
idx_user_time索引,否则全表扫描——确认
EXPLAIN显示
key列为该索引 如果用户删过历史,要加
WHERE is_deleted = 0过滤,否则软删除失效
正确示例:
SELECT keyword, search_count, created_at FROM search_history WHERE user_id = 123 AND is_deleted = 0 ORDER BY created_at DESC LIMIT 10;
别在应用层做排序和截断——数据库没加
ORDER BY时,
LIMIT返回顺序不保证,尤其分库分表后更危险。
实际最难的不是建表或查数据,是决定什么时候清理旧记录。自动定时删?按用户配额限制条数?这些策略得和业务方对齐,数据库只负责高效存取,别替产品做决策。
