复制代码

为懒人提供无限可能,生命不息,code不止

人类感性的情绪,让我们知难行难
我思故我在
日拱一卒,功不唐捐
  • 首页
  • 前端
  • 后台
  • 数据库
  • 运维
  • 资源下载
  • 实用工具
  • 接口文档工具
  • 登录
  • 注册

ERP

【原创】经销存商品档案数据表及查询优化方法

作者: whooyun发表于: 2024-06-10 21:54

业务场景:
1万企业,每个企业平均3个分店,每个机构3万商品sku,使用白名单模式进行机构商品档案管理,收银机进行机构商品档案下载时需要进行深度分页下载3万的sku
Mysql数据库设计:
1、商品基础信息表(1万X3万=3亿)
2、商品附加信息表(1万X3万=3亿)
3、商品价格表(1万X3万=3亿)
4、机构商品独立信息表(1万X3X3万=9亿),包含机构商品经营状态,生命周期
5、机构商品价格表(1万X3X3万=9亿)

特点:
1、浅分页的时候,查询前几十页可能数据,响应可能会比较快,但是随着分页深度变大,响应时间会越来越大
2、无法纯粹通过新建索引优化,比如创建时间,修改时间普通索引,或者id的主键索引,也无法通过查询字段和排序字段创建联合索引(覆盖索引),避免回表(因为查询的字段多达50个)优化

解决方案:
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" ]
}

---------------------------------------------------------------
闲聊:
后期复盘,进销存SaaS的企业分店卖的东西具有90%以上的相似度,也就是说一个企业开10个分店,或者100个分店,分店卖的商品有90%以上的相似度,
所以采用机构商品档案黑名单模式能更加简化业务的复杂度,提升用户体验。
1、设置完总部的商品档案,然后其余机构沿用总部的商品档案,单独进行商品生命周期,价格管理即可,也就是说商品档案数量只有3万,而不是3万X分店数
2、如果分支机构售卖商品跟总部有部分出入,其余机构直接只需要设置当前机构不卖的商品黑名单即可,也就是说商品档案数量也会减少指数倍