解决方案:
1、主键id为自增状态,基于主键id自增特征进行优化设计,每次查询都回传最大的id值,这样可以减少扫描的范围
SELECT id, name, createTime
FROM your_table
WHERE id > ?
ORDER BY id
LIMIT 1000;
2、通过辅助分页进行查询
CREATE TABLE page_info (
page_num INT PRIMARY KEY,
last_id INT,
corp_id INT,
org_id INT
);
###处理已有数据(当机构商品档案需要上架新商品时需要连带处理)
INSERT INTO page_info (page_num, last_id,corp_id,org_id)
SELECT FLOOR((row_number() OVER (ORDER BY id) - 1) / 1000) + 1 AS page_num, id
FROM your_table
WHERE (row_number() OVER (ORDER BY id) - 1) % 1000 = 0;
SELECT t1.id, t1.name, t1.createTime
FROM your_table t1
JOIN page_info t2 ON t1.id > t2.last_id
WHERE t2.page_num = ?
ORDER BY t1.id
LIMIT 1000;
3、子查询id,减少扫描行数
SELECT t1.id, t1.name, t1.createTime
FROM your_table t1
JOIN (
SELECT id
FROM your_table
WHERE id > ?
ORDER BY id
LIMIT 1000
) t2 ON t1.id = t2.id
ORDER BY t1.id;
================================================elasticsearch 搜索引擎方案====================================================
注意事项:在elasticsearch中创建宽表,保存商品档案及价格的所有信息
1、直接使用elasticsearch的原生search方案,并将max_result_window设置更大些(默认1万
设置max_result_window成3万,在现有单机构3万机构商品的情况下,响应时间不会有非常明显的缓慢,主要需要警惕内存oom
1、search_after 方案(推荐)
使用 search_after 可以避免 Elasticsearch 在深度分页时重复扫描已经分页过的数据。
POST /user/_search
{
"size": 1000,
"query": {
"match_all": {}
},
"sort": [
{ "modify_time": "asc" },
{ "id": "asc" }
],
"search_after": [ "2023-06-01T00:00:00", "12345" ]
}
3、scrollId(在现有机构商品稳定的情况下可以使用,但是如果处于开业初期,并发商品建档会影响查询准确度)
scroll API 适用于处理大量数据的情况。它会创建一个快照,允许你滚动浏览数据,但它有一个缺点是需要在短时间内处理完所有数据。
4. Point In Time (PIT)
PIT(时间点)是一种比 scroll 更现代化且资源效率更高的方式。PIT 允许你在分页过程中保持索引的稳定性,并且不会占用太多资源。
一、创建PIT POST /user/_pit?keep_alive=1m
二、使用PIT进行查询
POST /user/_search
{
"pit": {
"id": "your_pit_id",
"keep_alive": "1m"
},
"size": 1000,
"query": {
"match_all": {}
},
"sort": [
{ "timestamp": "asc" },
{ "id": "asc" }
],
"search_after": [ "2023-06-01T00:00:00", "12345" ]
}