React 进阶优化概念(6 个)——从能写组件到写好组件(下)| 葡萄城技术团队
React 进阶优化概念(6 个)——从能写组件到写好组件(下)
前言:为什么需要进阶概念?
国内开发者在 React 项目迭代中,常会遇到两个问题:
- “性能瓶颈”:比如列表渲染卡顿、组件反复重渲染;
- “复杂状态难管理”:比如购物车多商品操作、表单多字段联动。
这篇整理的 6 个进阶概念,就是解决这些问题的“钥匙”:从useRef
操作 DOM,到useMemo
/useCallback
优化性能,再到自定义 Hooks 复用逻辑,每个都针对国内项目高频痛点,帮你从“能写组件”升级到“写好组件”。
1. React 中 useRef 的使用:不止是 DOM 操作
核心作用
useRef
返回一个“持久化的 ref 对象”,它有两个核心用途:
- 操作 DOM:获取 DOM 元素的引用(如获取输入框焦点、读取元素尺寸);
- 保存持久化数据:数据更新时不会触发组件重渲染(如保存定时器 ID、上一次的状态值)。
国内开发中,useRef
常用来解决“无法获取最新状态”的问题(比如定时器中访问过时的 state),或实现“输入框自动聚焦”(表单场景高频需求)。
国内项目示例:DOM 操作+持久化数据(双场景实战)
import React, { useState, useRef, useEffect } from 'react';
import { Input, Button, message } from 'antd';
const UseRefDemo = () => {
const [count, setCount] = useState(0);
// 1. 用途1:操作DOM——获取输入框引用
const inputRef = useRef(null);
// 2. 用途2:保存持久化数据——定时器ID(更新不触发重渲染)
const timerRef = useRef(null);
// 示例1:输入框自动聚焦(页面加载后、点击按钮时)
useEffect(() => {
// 页面加载后,让输入框聚焦(国内表单常见需求)
inputRef.current.focus();
}, []);
const handleFocusInput = () => {
// 点击按钮,让输入框聚焦
inputRef.current.focus();
};
// 示例2:定时器计数(用useRef保存定时器ID,避免重复创建)
const startTimer = () => {
if (timerRef.current) return; // 避免重复启动定时器
timerRef.current = setInterval(() => {
// 定时器中用函数式更新,确保获取最新的count
setCount(prevCount => prevCount + 1);
}, 1000);
};
const stopTimer = () => {
// 清除定时器(用useRef保存的ID)
clearInterval(timerRef.current);
timerRef.current = null;
};
// 组件卸载时清除定时器,避免内存泄漏
useEffect(() => {
return () => {
clearInterval(timerRef.current);
};
}, []);
return (
<div style="{{" padding: 24, width: 400 }}>
<h3>useRef 双场景示例</h3>
{/* 输入框:ref={inputRef} 绑定DOM引用 */}
<input ref="{inputRef}" placeholder="我会自动聚焦" style="{{" marginBottom: 16 }}>
<button onclick="{handleFocusInput}" style="{{" marginbottom: 16 }}>
让输入框聚焦
</button>
<divider />
<div style="{{" marginbottom: 16 }}>
<span>定时器计数:{count} 秒</span>
</div>
<space size="middle">
<button onclick="{startTimer}" type="primary">
开始计数
</button>
<button onclick="{stopTimer}" danger>
停止计数
</button>
</space>
</div>
);
};
export default UseRefDemo;
2. React useReducer Hook 详解:什么时候用它代替 useState?
核心作用
useReducer
是“复杂状态管理”的 Hook,它接收一个“ reducer 函数”和“初始状态”,返回当前状态和“dispatch 函数”(用于触发状态更新)。
当状态满足以下条件时,用useReducer
比useState
更合适(国内项目高频场景):
- 状态是“对象/数组”(如购物车商品列表、表单多字段);
- 状态更新逻辑复杂(如购物车的“添加/删除/修改数量/清空”);
- 多个子组件需要修改同一状态(通过 dispatch 统一触发)。
国内项目示例:电商购物车(useReducer 实战)
import React, { useReducer } from 'react';
import { Card, List, Button, InputNumber, Space, message } from 'antd';
// 1. 定义reducer函数(处理状态更新逻辑)
// state:当前状态;action:描述“做什么”(type+payload)
const cartReducer = (state, action) => {
switch (action.type) {
// 1. 添加商品到购物车
case 'ADD_ITEM': {
// 检查商品是否已在购物车中
const existingItem = state.find(item => item.id === action.payload.id);
if (existingItem) {
// 已存在:更新数量
return state.map(item =>
item.id === action.payload.id
? { ...item, quantity: item.quantity + action.payload.quantity }
: item
);
} else {
// 不存在:新增商品
return [...state, action.payload];
}
}
// 2. 修改商品数量
case 'UPDATE_QUANTITY':
return state.map(item =>
item.id === action.payload.id
? { ...item, quantity: action.payload.quantity }
: item
);
// 3. 删除商品
case 'REMOVE_ITEM':
return state.filter(item => item.id !== action.payload.id);
// 4. 清空购物车
case 'CLEAR_CART':
return [];
// 默认:返回原状态
default:
return state;
}
};
// 2. 购物车组件
const ShoppingCart = () => {
// 初始化购物车状态(国内电商常见的商品结构)
const initialState = [
{ id: 1, name: '华为Mate 60 Pro', price: 6999, quantity: 1, img: '/images/mate60.jpg' },
{ id: 2, name: '小米14', price: 4999, quantity: 1, img: '/images/mi14.jpg' },
];
// 调用useReducer:获取state和dispatch
const [cartItems, dispatch] = useReducer(cartReducer, initialState);
// 计算总价(国内电商购物车必备)
const totalPrice = cartItems.reduce(
(total, item) => total + item.price * item.quantity,
0
);
// 触发状态更新的方法(调用dispatch,传递action)
const addItem = () => {
// 模拟添加新商品
const newItem = {
id: 3,
name: 'iPhone 15',
price: 7999,
quantity: 1,
img: '/images/iphone15.jpg',
};
dispatch({ type: 'ADD_ITEM', payload: newItem });
message.success('商品已添加到购物车');
};
const updateQuantity = (id, quantity) => {
// 数量不能小于1
if (quantity < 1) return;
dispatch({ type: 'UPDATE_QUANTITY', payload: { id, quantity } });
};
const removeItem = (id) => {
dispatch({ type: 'REMOVE_ITEM', payload: { id } });
};
const clearCart = () => {
dispatch({ type: 'CLEAR_CART' });
};
return (
<card title="我的购物车" style="{{" width: 800, margin: '0 auto', padding: 24 }}>
{cartItems.length === 0 ? (
<div style="{{" textalign: 'center', padding: 40 }}>
<p>购物车为空</p>
<button onclick="{addItem}" type="primary">
添加示例商品
</button>
</div>
) : (
<>
<list datasource="{cartItems}" renderitem="{(item)" => (
<list.item key="{item.id}" actions="{[" <button danger onclick="{()" => removeItem(item.id)}>
删除
]}
>
<list.item.meta avatar="{<img" src="{item.img}" alt="{item.name}" style="{{" width: 60, height: 60 }} />}
title={item.name}
description={`单价:¥${item.price}`}
/>
<div>
{/* 数量调整:国内电商常见的InputNumber */}
<inputnumber min="{1}" value="{item.quantity}" onchange="{(quantity)" => updateQuantity(item.id, quantity)}
style={{ marginRight: 16 }}
/>
<span style="{{" color: '#f40' }}>¥{item.price * item.quantity}</span>
</inputnumber></div>
</list.item>
)}
/>
<div style="{{" textalign: 'right', margintop: 16 }}>
<space size="middle">
<button onclick="{clearCart}">清空购物车</button>
<button onclick="{addItem}" type="primary">
添加商品
</button>
<div style="{{" fontsize: 18, color: '#f40' }}>
总价:¥{totalPrice.toFixed(2)}
</div>
</space>
</div>
)}
</list></card>
);
};
export default ShoppingCart;
3. React 中的 useMemo:通过记忆化优化性能
核心作用
useMemo
是“记忆化值”的 Hook,它接收一个“计算函数”和“依赖数组”,只有当依赖数组中的值变化时,才会重新执行计算函数并返回新值;否则直接返回“缓存的旧值”。
国内开发中,useMemo
主要用于优化“昂贵的计算”(如大数据排序、复杂列表过滤),避免组件每次重渲染时都重复执行耗时计算,导致页面卡顿。
国内项目示例:大数据列表过滤(useMemo 优化)
import React, { useState, useMemo } from 'react';
import { Input, List, Card, Spin } from 'antd';
// 模拟大数据(国内后台常见的“用户列表”,1000条数据)
const generateBigData = () => {
return Array.from({ length: 1000 }, (_, i) => ({
id: i + 1,
username: `user_${i + 1}`,
role: i % 3 === 0 ? '管理员' : i % 3 === 1 ? '编辑' : '普通用户',
department: `部门_${Math.floor(i / 100) + 1}`,
}));
};
const BigDataFilter = () => {
const [searchText, setSearchText] = useState('');
const bigData = generateBigData(); // 模拟接口返回的大数据
// 昂贵的计算:根据搜索框过滤数据(遍历1000条数据)
// 用useMemo记忆化结果:只有searchText变化时才重新过滤
const filteredData = useMemo(() => {
console.log('执行过滤计算(仅searchText变化时触发)');
// 模拟耗时计算(实际项目中可能更复杂)
return bigData.filter(item =>
item.username.includes(searchText) ||
item.role.includes(searchText) ||
item.department.includes(searchText)
);
}, [searchText, bigData]); // 依赖:searchText或bigData变化时重新计算
// 普通计算(无useMemo):每次组件重渲染都会执行
const unoptimizedData = bigData.filter(item =>
item.username.includes(searchText)
);
console.log('未优化的过滤计算(每次重渲染都触发)');
return (
<card title="大数据列表过滤(useMemo优化)" style="{{" width: 800, margin: '0 auto', padding: 24 }}>
{/* 搜索框:输入变化触发组件重渲染 */}
<input placeholder="搜索用户名/角色/部门" value="{searchText}" onChange="{(e)" => setSearchText(e.target.value)}
style={{ marginBottom: 16 }}
/>
<h4>优化后的数据(useMemo):{filteredData.length} 条</h4>
<list datasource="{filteredData}" renderitem="{(item)" => (
<list.item key="{item.id}">
<span>{item.username}</span> ·
<span style="{{" margin: '0 8px' }}>{item.role}</span> ·
<span>{item.department}</span>
</list.item>
)}
pagination={{ pageSize: 10 }}
style={{ marginBottom: 24 }}
/>
<h4>未优化的数据(无useMemo):{unoptimizedData.length} 条</h4>
<list datasource="{unoptimizedData}" renderitem="{(item)" => (
<list.item key="{item.id}">{item.username}</list.item>
)}
pagination={{ pageSize: 10 }}
/>
</list></list></card>
);
};
export default BigDataFilter;
注意点(国内开发者常踩的坑)
useMemo
不是“越多越好”:简单计算(如a + b
)用useMemo
反而会增加缓存开销,只优化“耗时计算”;- 依赖数组必须完整:如果计算函数中用到了组件内的状态/属性,必须加到依赖数组中,否则会获取到过时的值。
4. React 中的 useCallback:记忆化函数避免重复创建
核心作用
useCallback
是“记忆化函数”的 Hook,它接收一个“函数”和“依赖数组”,只有当依赖数组中的值变化时,才会返回新的函数;否则直接返回“缓存的旧函数”。
国内开发中,useCallback
主要用于解决“子组件不必要的重渲染”问题——当父组件传给子组件的函数“每次都重新创建”时,即使子组件用了React.memo
(记忆化组件),也会触发重渲染。用useCallback
缓存函数,能让子组件只在必要时重渲染。
国内项目示例:父子组件优化(useCallback+React.memo)
import React, { useState, useCallback } from 'react';
import { Button, Card, Space } from 'antd';
// 子组件:商品卡片(用React.memo记忆化,避免不必要重渲染)
const ProductItem = React.memo(({ product, onAddToCart }) => {
console.log(`商品 ${product.name} 组件重渲染`); // 查看重渲染情况
return (
<card title="{product.name}" style="{{" width: 240, margin: '16px' }}>
<p>价格:¥{product.price}</p>
<button type="primary" danger onclick="{()" => onAddToCart(product.id)}
style={{ width: '100%', marginTop: 12 }}
>
加入购物车
</button>
</card>
);
});
// 父组件:商品列表
const ProductList = () => {
const [count, setCount] = useState(0); // 父组件状态(与子组件无关)
const [products] = useState([
{ id: 1, name: '华为Mate 60 Pro', price: 6999 },
{ id: 2, name: '小米14', price: 4999 },
{ id: 3, name: 'iPhone 15', price: 7999 },
]);
// 未优化的函数:每次父组件重渲染都会创建新函数
const unoptimizedAddToCart = (productId) => {
console.log(`添加商品 ${productId} 到购物车`);
};
// 优化的函数:用useCallback缓存,只有依赖变化时才创建新函数
const optimizedAddToCart = useCallback((productId) => {
console.log(`添加商品 ${productId} 到购物车`);
// 如果函数中用到count,需要把count加到依赖数组中
// console.log('当前购物车数量:', count);
}, []); // 依赖数组:此处无依赖,函数永远是同一个引用
return (
<div style="{{" padding: 24 }}>
<h2>商品列表(useCallback优化)</h2>
{/* 点击按钮修改count,触发父组件重渲染 */}
<space style="{{" marginbottom: 16 }}>
<button onclick="{()" => setCount(count + 1)}>
点击触发父组件重渲染(count:{count})
</button>
<p>观察控制台:子组件是否重渲染</p>
</space>
<h4>未优化的子组件(传普通函数)</h4>
<div style="{{" display: 'flex', flexwrap: 'wrap' }}>
{products.map(product => (
<productitem key="{product.id}" product="{product}" onAddToCart="{unoptimizedAddToCart}" 每次都传新函数 />
))}
</div>
<h4 style="{{" margintop: 24 }}>优化的子组件(传useCallback缓存的函数)</h4>
<div style="{{" display: 'flex', flexwrap: 'wrap' }}>
{products.map(product => (
<productitem key="{product.id}" product="{product}" onAddToCart="{optimizedAddToCart}" 传缓存的函数 />
))}
</div>
</div>
);
};
export default ProductList;
关键搭配
useCallback
通常和React.memo
一起使用:
React.memo
:让子组件只在 props 变化时重渲染;useCallback
:确保父组件传给子组件的函数“不轻易变化”,避免React.memo
失效。
5. 创建 React 自定义 Hook:复用组件逻辑
核心作用
自定义 Hook 是“抽取和复用组件逻辑”的方式,它本质是“命名以 use 开头的函数”,可以调用其他 Hook(如useState
、useEffect
)。
国内开发中,自定义 Hook 能解决“逻辑重复”问题——比如多个组件都需要“获取用户位置”“处理表单验证”“监听滚动事件”,把这些逻辑抽成自定义 Hook,能让代码更简洁、易维护。
国内项目示例:3 个高频自定义 Hook(表单验证+接口请求+滚动监听)
import React, { useState, useEffect, useCallback } from 'react';
import { Input, Button, message, Form } from 'antd';
// 自定义Hook 1:表单验证(国内表单高频需求)
const useFormValidation = (initialValues, validateRules) => {
const [values, setValues] = useState(initialValues);
const [errors, setErrors] = useState({});
const [isValid, setIsValid] = useState(false);
// 验证逻辑
const validate = useCallback(() => {
const newErrors = {};
// 遍历验证规则(如必填、手机号格式)
Object.entries(validateRules).forEach(([key, rule]) => {
const value = values[key];
if (rule.required && !value) {
newErrors[key] = rule.message || `${key}不能为空`;
} else if (rule.pattern && value && !rule.pattern.test(value)) {
newErrors[key] = rule.message || `${key}格式错误`;
}
});
setErrors(newErrors);
setIsValid(Object.keys(newErrors).length === 0);
return newErrors;
}, [values, validateRules]);
// 输入变化时更新值
const handleChange = (e) => {
const { name, value } = e.target;
setValues(prev => ({ ...prev, [name]: value }));
};
// 提交前验证
const handleSubmit = (onSubmit) => () => {
const newErrors = validate();
if (Object.keys(newErrors).length === 0) {
onSubmit(values);
}
};
return { values, errors, isValid, handleChange, handleSubmit, validate };
};
// 自定义Hook 2:接口请求(国内项目通用请求逻辑)
const useFetch = (url, options = {}) => {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(false);
const [error, setError] = useState(null);
const fetchData = useCallback(async () => {
setLoading(true);
try {
const res = await fetch(url, {
headers: {
'Content-Type': 'application/json',
...options.headers,
},
...options,
});
if (!res.ok) throw new Error(`请求失败:${res.status}`);
const result = await res.json();
setData(result);
setError(null);
} catch (err) {
setError(err.message);
setData(null);
message.error(err.message);
} finally {
setLoading(false);
}
}, [url, options]);
// 初始请求(如果需要)
useEffect(() => {
if (options.autoFetch !== false) {
fetchData();
}
}, [fetchData, options.autoFetch]);
return { data, loading, error, refetch: fetchData };
};
// 自定义Hook 3:滚动监听(国内H5高频需求)
const useScroll监听 = (targetId) => {
const [isScrolledToTarget, setIsScrolledToTarget] = useState(false);
useEffect(() => {
const handleScroll = () => {
const targetElement = document.getElementById(targetId);
if (!targetElement) return;
// 计算目标元素是否进入视口
const rect = targetElement.getBoundingClientRect();
const isInView = rect.top <= window.innerHeight / 2 && rect.bottom >= 0;
setIsScrolledToTarget(isInView);
};
window.addEventListener('scroll', handleScroll);
handleScroll(); // 初始检查
return () => {
window.removeEventListener('scroll', handleScroll);
};
}, [targetId]);
return isScrolledToTarget;
};
// 使用自定义Hook:表单组件
const LoginForm = () => {
// 使用useFormValidation
const { values, errors, handleChange, handleSubmit } = useFormValidation(
{ username: '', phone: '' }, // 初始值
{ // 验证规则
username: { required: true, message: '请输入用户名' },
phone: {
required: true,
message: '请输入手机号',
pattern: /^1[3-9]\d{9}$/ // 国内手机号正则
},
}
);
// 表单提交
const onLogin = (values) => {
console.log('登录提交:', values);
message.success('登录验证通过');
};
return (
<form style="{{" width: 350, margin: '0 auto' }}>
<form.item label="用户名" validatestatus="{errors.username" ? 'error' : ''} help="{errors.username}">
<input name="username" value="{values.username}" onChange="{handleChange}" placeholder="请输入用户名">
</form.item>
<form.item label="手机号" validatestatus="{errors.phone" ? 'error' : ''} help="{errors.phone}">
<input name="phone" value="{values.phone}" onChange="{handleChange}" placeholder="请输入手机号">
</form.item>
<form.item>
<button type="primary" onclick="{handleSubmit(onLogin)}" style="{{" width: '100%' }}>
登录
</button>
</form.item>
</form>
);
};
// 使用自定义Hook:接口请求组件
const UserData = () => {
// 使用useFetch请求用户信息(autoFetch: true 初始自动请求)
const { data, loading } = useFetch('/api/user', { autoFetch: true });
if (loading) return <spin style="{{" display: 'block', margin: '40px auto' }} />;
return (
<div style="{{" padding: 24 }}>
<h3>用户信息</h3>
{data && (
<div>
<p>用户名:{data.username}</p>
<p>手机号:{data.phone}</p>
<p>角色:{data.role}</p>
</div>
)}
</div>
);
};
// 组合使用
const CustomHooksDemo = () => {
// 使用useScroll监听:监听id为"target"的元素
const isTargetInView = useScroll监听('target');
return (
<div style="{{" padding: 24 }}>
<h2>自定义Hook示例</h2>
<loginform />
<userdata />
<div style="{{" height: 1000 }}> {/* 占位,让页面可滚动 */}
<p>滚动到下方目标区域...</p>
</div>
<div id="target" style="{{" padding: 24, background: istargetinview ? '#f0f7ff' : '#fff', border: '1px solid #1890ff' #eee' }}>
<h3>目标区域</h3>
<p>{isTargetInView ? '已进入视口' : '未进入视口'}</p>
</div>
</div>
);
};
export default CustomHooksDemo;
6. 最常用 React Hooks 对比:什么时候用哪个?
核心问题
国内开发者在实际开发中,常困惑“该用 useState 还是 useReducer?”“useMemo 和 useCallback 有啥区别?”——这部分通过对比表格和场景总结,帮你快速判断“什么场景用什么 Hook”。
1. 状态管理类 Hook 对比(useState vs useReducer)
对比维度 | useState | useReducer |
---|---|---|
适用场景 | 简单状态(数字、字符串、简单对象) | 复杂状态(多字段对象、数组,复杂更新逻辑) |
状态更新逻辑 | 直接在 setter 中写(如setCount(c+1) ) |
集中在 reducer 函数中(统一管理) |
组件通信 | 需手动传 setter 给子组件 | 传 dispatch 给子组件(更简洁) |
调试体验 | 难追踪状态变化原因 | 可通过 action type 追踪状态变化 |
国内项目示例 | 计数器、输入框内容、弹窗显示/隐藏 | 购物车、表单多字段、复杂列表状态 |
2. 性能优化类 Hook 对比(useMemo vs useCallback)
对比维度 | useMemo | useCallback |
---|---|---|
作用对象 | 记忆化“值”(如计算结果、数组) | 记忆化“函数”(如事件处理函数、回调函数) |
返回值 | 记忆化后的值 | 记忆化后的函数引用 |
适用场景 | 优化昂贵的计算(如大数据过滤、排序) | 避免子组件不必要的重渲染(配合 React.memo) |
国内项目示例 | 大数据列表过滤结果、图表计算数据 | 父组件传给子组件的事件处理函数、列表项点击函数 |
3. 其他常用 Hook 适用场景
Hook | 核心作用 | 国内项目高频场景 |
---|---|---|
useContext | 跨层级传递数据,避免属性透传 | 全局主题、用户信息、语言设置 |
useRef | 操作 DOM、保存持久化数据(不触发重渲染) | 输入框聚焦、保存定时器 ID、获取最新状态 |
useEffect | 管理副作用(请求、DOM 操作、定时器) | 接口请求、监听事件、清理定时器 |
4. 国内项目 Hook 选择流程图(简化版)
- **需要管理状态?**→ 简单状态(1-2 个字段)→ useState→ 复杂状态(多字段/复杂更新)→ useReducer
- **需要处理副作用?**→ 请求数据、监听事件、清理资源 → useEffect
- **需要跨层级传数据?**→ 创建 Context + useContext
- **需要优化性能?**→ 优化计算结果 → useMemo→ 优化函数传递 → useCallback(配合 React.memo)
- **需要操作 DOM 或保存持久化数据?**→ useRef
下篇小结
这 6 个进阶概念,是 React 项目“从能用 to 好用”的关键:
useRef
帮你解决“DOM 操作”和“持久化数据”的问题;useReducer
让复杂状态管理更清晰;useMemo
/useCallback
帮你优化性能,避免页面卡顿;- 自定义 Hook 让逻辑复用更简单;
- Hooks 对比表则帮你快速选择合适的工具。
掌握这些概念后,你不仅能应对国内大部分 React 业务场景(如电商、后台、H5),还能写出更易维护、性能更好的代码——这也是从“初级 React 开发者”到“中级开发者”的核心跨越。

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
-
上一篇
用 SeaTunnel 同步 MySQL 到 Doris:全量增量 + SQL 过滤
Apache SeaTunnel 能够实现 MySQL 到 Doris 的全量和增量数据同步,同时也支持 SQL 级别的数据过滤。以下是具体实现方式及功能特点: 全量与增量同步支持 1. 全量同步 实现方式:通过 SeaTunnel 的批处理模式(job.mode = "BATCH"),将 MySQL 的历史数据一次性导入 Doris。支持分片读取(如按主键分片)以提升效率,并可通过配置参数优化并行度、批量写入大小等。 source { Jdbc { query = "SELECT * FROM orders" -- 全量数据读取 partition_column = "id" -- 分片字段 split.size = 5000 -- 每分片读取行数 } } 2. 增量同步 基于时间戳字段:通过WHERE update_time >= '${last_update_time}'动态参数筛选增量数据,需外部系统记录时间点并触发定期任务。 基于 CDC(变更数据捕获):使用 MySQL CDC 连接器实时捕获 Binlog 变更(如插入、更新、删除),同步至 Doris。支持...
-
下一篇
(三)数仓人必看!ODS 到 DWS 各层设计规范全解析,含同步/存储/质量核心要点
《新兴数据湖仓设计与实践手册·数据湖仓建模及模型命名规范(2025年)》 由四篇递进式指南组成,以"模型架构---公共规范---分层规范---命名规范"为主线,系统构建可演进、可治理、可共享的现代数据湖仓。 本文为系列文章第三篇,详细剖析了数仓各层的设计规范,包含同步、存储、质量等核心要点。 最后一篇将在此框架内,依次剖析数仓各层的命名规范,帮助企业用一套方法论完成从数据入湖到价值变现的全链路建设,敬请期待完整版。 ODS层设计规范 同步规范: 一个系统源表只允许同步一次; 全量初始化同步和增量同步处理逻辑要清晰; 以统计日期和时间进行分区存储; 目标表字段在源表不存在时要自动填充处理。 表分类与生命周期: 1. ods流水全量表: 不可再生的永久保存; 日志可按留存要求; 按需设置保留特殊日期数据; 按需设置保留特殊月份数据; 2. ods镜像型全量表: 推荐按天存储; 对历史变化进行保留; 最新数据仓储在最大分区; 历史数据按需保留; 3. ods增量数据: 推荐按天存储; 有对应全量表的,建议只保留14天数据; 无对应全量表的,永久保留; 4. ods的etl过程中的临时表: 推...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- CentOS6,7,8上安装Nginx,支持https2.0的开启
- CentOS7编译安装Gcc9.2.0,解决mysql等软件编译问题
- SpringBoot2初体验,简单认识spring boot2并且搭建基础工程
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- SpringBoot2更换Tomcat为Jetty,小型站点的福音
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装
- MySQL数据库在高并发下的优化方案
- SpringBoot2整合Redis,开启缓存,提高访问速度
- Docker安装Oracle12C,快速搭建Oracle学习环境
- Mario游戏-低调大师作品