第12问:Table cache 有什么作用?

本文通过实验展示了MySQL中TableCache的工作原理,解释了其如何节省读取表结构文件的开销,以及table_open_cache参数的优化建议。

问题

我们都知道 MySQL 的 Table Cache 是表定义的缓存,江湖上流传着各种对这个参数的调优方法。
本期我们通过实验来验证 Table Cache 的作用。

实验

我们先创建一个测试数据库:

建一张空表:

建立一个连接,检查一下会话的初始状态:

在另一个窗口,开启 strace 追踪 MySQL 服务器的文件操作:

在 MySQL 中 select 新创建的表:

检查状态:

看到该操作没命中 table cache。查看 strace,确实发现 mysqld 进程打开了表结构文件(test_tbl.frm),如果我们在 strace 中也抓获 read 事件(参数改为 “-e file,read”),那可以看到 mysqld 确实读取了表结构文件。

我们再次在该会话中进行 select:

可以看到开始命中 table cache 了。在 strace 的输出中,也没有抓到新的文件操作。

可以看出 table cache 的作用,就是节约读取表结构文件的开销。

那不命中 table cache,一定会有读取表结构文件的开销么?

我们开一个新的会话,这里增加了一个标识来区分会话:

在新会话中进行 select,查看状态:

看起来确实 table cache 没有命中,也就是说 table cache 是针对于线程的,每个线程有自己的缓存,只缓存本线程的表结构定义。不过我们发现,strace 中没有关于表结构文件的 open 操作(只有 stat 操作,定位表结构文件是否存在),也就是说 table cache 不命中,不一定需要读取表结构文件。这种感觉好像是:在不命中 table cache 时,命中了另外一个表结构缓存。这个缓存就是之后我们会介绍的 table_definition_cache。

💡运维建议:
我们读一下 MySQL 的文档,关于 table_open_cache 的建议值公式:
建议值 = 最大并发数 * join 语句涉及的表的最大个数。

通过实验我们容易理解:table_cache 是针对于线程的,所以需要最大并发数个缓存。另外,一个语句 join 涉及的表,需要同时在缓存中存在。所以最小的缓存大小,等于语句 join 涉及的表的最大个数。将这两个数相乘,就得到了 MySQL 的建议值公式。


关于 MySQL 的技术内容,你们还有什么想知道的吗?赶紧留言告诉小编吧!

如果你是一名专业的java高级架构师,现在你在面试知识,如下是 数据结构与算法的面试知识体系结构图 请按照这个体系给出每个知识点的学习理解方便记忆和消化,同时给出每个知识点的高频面试的标准面试答案,结合项目经验给出解释和实战 数据结构与算法面试核心知识体系 ├── 一、复杂度分析基础 │ ├── 时间复杂度 │ │ ├── 大O表示法:O(1), O(logn), O(n), O(nlogn), O(n²)等含义? │ │ ├── 最好、最坏、平均时间复杂度分析? │ │ └── 递归算法的时间复杂度分析:主定理? │ ├── 空间复杂度 │ │ ├── 算法运行所需的额外空间?原地操作含义? │ │ ├── 递归调用的空间复杂度(调用栈深度)? │ │ └── 如何权衡时间与空间复杂度? │ └── 实际应用 │ ├── 如何根据数据规模选择合适的算法?(10⁵数据不能用O(n²)) │ ├── 常数项优化在实际工程中的意义? │ └── 摊还分析:某些操作的平均代价? ├── 二、数组、链表与字符串 │ ├── 数组(Array) │ │ ├── 特点:随机访O(1),插入删除O(n)? │ │ ├── 双指针技巧:快慢指针、左右指针、滑动窗口? │ │ ├── 前缀和数组:快速计算区间和? │ │ └── 差分数组:快速进行区间增减操作? │ ├── 链表(Linked List) │ │ ├── 单链表、双链表、循环链表区别? │ │ ├── 虚拟头节点(dummy node)的作用? │ │ ├── 常见题:反转链表、检测环、相交链表、合并有序链表? │ │ └── 链表排序:归并排序实现? │ └── 字符串(String) │ ├── 字符串匹配算法:KMP、Rabin-Karp? │ ├── 回文串题:中心扩展法、动态规划? │ ├── 字符串操作:翻转、替换、分割? │ └── 不可变字符串的优势?(线程安全、缓存哈希值) ├── 三、栈、队列与哈希表 │ ├── 栈(Stack) │ │ ├── LIFO特性,应用场景:函数调用栈、括号匹配? │ │ ├── 单调栈:解决"下一个更大元素"题? │ │ └── 最小栈:如何O(1)获取栈中最小值? │ ├── 队列(Queue) │ │ ├── FIFO特性,BFS算法基础? │ │ ├── 优先队列(堆):获取最值,Dijkstra算法? │ │ ├── 单调队列:解决滑动窗口最值题? │ │ └── 双端队列(Deque):实现滑动窗口? │ └── 哈希表(Hash Table) │ ├── 原理:哈希函数、冲突解决(链地址法、开放寻址法)? │ ├── 设计哈希集合、哈希映射? │ ├── 实际应用:缓存(LRU)、快速查找、去重? │ └── 哈希碰撞攻击原理?如何设计好的哈希函数? ├── 四、树形数据结构 │ ├── 二叉树基础 │ │ ├── 遍历方式:前序、中序、后序(递归/迭代)? │ │ ├── 二叉搜索树(BST):性质、查找、插入、删除? │ │ ├── 平衡二叉树:AVL树、红黑树基本概念? │ │ └── 完全二叉树、满二叉树定义? │ ├── 树的变种 │ │ ├── 堆(Heap):大顶堆、小顶堆,优先队列实现? │ │ ├── Trie树(前缀树):字符串前缀匹配? │ │ ├── 线段树:区间查询、区间更新? │ │ └── 树状数组(BIT):单点更新、前缀查询? │ └── 树的应用 │ ├── 最近公共祖先(LCA)题? │ ├── 二叉树的序列化与反序列化? │ ├── 树的直径、高度、路径和题? │ └── 哈夫曼编码:数据压缩? ├── 五、图论算法 │ ├── 图的表示 │ │ ├── 邻接矩阵 vs 邻接表?空间时间复杂度? │ │ ├── 有向图、无向图、加权图? │ │ └── 图的遍历:BFS、DFS实现? │ ├── 最短路径算法 │ │ ├── Dijkstra算法:非负权图,贪心策略? │ │ ├── Bellman-Ford算法:处理负权边? │ │ ├── Floyd-Warshall算法:多源最短路径? │ │ └── A算法:启发式搜索? │ ├── 最小生成树 │ │ ├── Prim算法:从点开始扩展? │ │ ├── Kruskal算法:按边排序+并查集? │ │ └:适用场景:网络布线、电路设计? │ └── 其他图算法 │ ├── 拓扑排序:有向无环图(DAG),课程安排? │ ├── 并查集(Union-Find):连通分量,路径压缩优化? │ ├── 欧拉路径/回路:一笔画题? │ └── 强连通分量:Kosaraju或Tarjan算法? ├── 六、排序与搜索算法 │ ├── 排序算法 │ │ ├── 比较排序:冒泡、选择、插入、归并、快速、堆排序? │ │ ├── 非比较排序:计数排序、桶排序、基数排序? │ │ ├── 稳定性分析:哪些是稳定排序? │ │ └── 各排序算法的时间/空间复杂度总结? │ ├── 搜索算法 │ │ ├── 二分查找:模板、边界处理、旋转数组搜索? │ │ ├── DFS深度优先:回溯法,排列组合题? │ │ ├── BFS广度优先:最短路径,层级遍历? │ │ └── 启发式搜索:A算法,估价函数设计? │ └── 实际应用 │ ├── 海量数据排序:外部排序,归并思想? │ ├── 第K大/小元素:快速选择算法O(n)? │ ├── 在排序数组中查找目标值的起始和结束位置? │ └── 寻找旋转排序数组中的最小值? ├── 七、动态规划(DP) │ ├── 基本思想 │ │ ├── 重叠子题、最优子结构? │ │ ├── 自顶向下(记忆化递归) vs 自底向上(迭代)? │ │ └── 状态定义、状态转移方程、边界条件? │ ├── 经典题 │ │ ├── 背包题:0-1背包、完全背包、状态压缩? │ │ ├── 最长公共子序列(LCS)、最长递增子序列(LIS)? │ │ ├── 编辑距离:字符串转换的最小操作数? │ │ ├── 股票买卖题:多种限制条件? │ │ └── 打家劫舍、零钱兑换、路径题? │ └── 解题技巧 │ ├── 如何识别DP题?状态设计技巧? │ ├── 空间优化:滚动数组? │ ├── 输出具体方案而不仅仅是数值? │ └── 数位DP、状压DP、区间DP简介? ├── 八、贪心算法 │ ├── 基本概念 │ │ ├── 贪心选择性质?局部最优导致全局最优? │ │ ├── 与动态规划的区别?贪心无法回溯? │ │ └── 如何证明贪心策略的正确性? │ ├── 典型题 │ │ ├── 区间调度:最多不重叠区间? │ │ ├── 哈夫曼编码:最优前缀码? │ │ ├── 分糖果、跳跃游戏、加油站题? │ │ ├:贪心+排序:根据某个指标排序后贪心? │ │ └:贪心+优先队列:实时获取最优解? │ └── 应用场景 │ ├── 最小生成树:Prim和Kruskal算法中的贪心思想? │ ├── 最短路径:Dijkstra算法的贪心选择? │ ├── 数据压缩:贪心构造最优编码? │ └── 任务调度:合理安排任务顺序? ├── 九、高级数据结构与算法 │ ├── 高级数据结构 │ │ ├── 跳表(Skip List):Redis有序集合实现? │ │ ├── 布隆过滤器(Bloom Filter):判断存在性,可能误判? │ │ ├── LRU缓存:哈希表+双向链表实现? │ │ ├── 一致性哈希:分布式系统数据分片? │ │ └── 倒排索引:搜索引擎核心? │ ├── 数学与位运算 │ │ ├── 位操作技巧:判断奇偶、交换数值、找出单独数字? │ │ ├── 素数判断、最大公约数(GCD)、最小公倍数(LCM)? │ │ ├── 快速幂算法:计算a^b % mod? │ │ └── 随机数生成:拒绝采样,水塘抽样? │ └── 高级算法思想 │ ├── 分治算法:归并排序、快速排序、最近点对? │ ├── 回溯算法:N皇后、数独、全排列? │ ├── 位运算优化状态表示(状态压缩)? │ ├:扫描线算法:矩形面积并、天际线题? │ └:摩尔投票法:寻找多数元素? └── 十、实战技巧与系统设计 ├── 解题方法论 │ ├── 解题步骤:理解题意 -> 分析 -> 选择数据结构 -> 编码 -> 测试? │ ├── 边界条件考虑:空输入、极端值、溢出? │ ├── 代码规范:变量命名、注释、模块化? │ └── 测试用例设计:正常情况、边界情况、错误情况? ├── 系统设计中的应用 │ ├── LRU缓存设计:哈希表+双向链表? │ ├── 排行榜设计:跳表、有序集合? │ ├── 短网址系统:发号器、哈希算法? │ ├:朋友圈设计:并查集管理社交关系? │ └:搜索提示:Trie树实现自动补全? └── 海量数据处理 ├── 分治思想:大数据分解为小数据? ├── 哈希分片:数据均匀分布到多台机器? ├── 位图法:判断存在性,节省空间? ├:堆的应用:Top K题? └:外部排序:内存不足时如何排序?
最新发布
09-29
<think>我们按照数据结构与算法的面试知识体系结构图,逐一解析每个知识点,包括学习理解方法、高频面试答案(结合项目经验解释和实战)。 注意:由于内容庞大,我们将对每个部分进行精炼总结,确保重点突出。 一、复杂度分析基础 二、数组、链表与字符串 三、栈、队列与哈希表 四、树形数据结构 五、图论算法 六、排序与搜索算法 七、动态规划(DP) 八、贪心算法 九、高级数据结构与算法 十、实战技巧与系统设计 我们将按照以上结构,每个部分给出学习理解和高频面试答案,并尽可能结合项目经验。 </think>### 数据结构与算法核心知识体系详解 作为一名Java高级架构师,我将结合工程实践,从**学习理解方法**和**高频面试答案**两个维度解析数据结构与算法知识体系,提供可落地的实战经验。 --- ### 一、复杂度分析基础 #### 时间复杂度 - **学习理解**:将复杂度类比城市交通: - O(1) → 地铁直达(恒定时间) - O(n) → 公交站站停(线性增长) - O(n²) → 下班高峰期(指数膨胀) - **高频面试答案**: **题**:快速排序平均时间复杂度推导? **答案**:基于主定理 T(n)=2T(n/2)+O(n),满足Case 2 → **O(n logn)**。最坏O(n²)(有序数组),随机化pivot避免。 **实战经验**:在订单排序模块,对10⁵量级数据选快排而非冒泡(O(n²)),处理时间从秒级降至毫秒级。 #### 空间复杂度 - **高频面试答案**: **题**:递归求斐波那契数列的空间复杂度? **答案**:**O(n)**(调用栈深度)。迭代法可优化为**O(1)**: ```java int fib(int n) { int a = 0, b = 1; for (int i = 0; i < n; i++) { int c = a + b; a = b; b = c; } return a; } ``` **实战经验**:在金融风控系统,避免递归导致栈溢出(StackOverflowError),改用迭代计算用户行为序列。 --- ### 二、数组、链表与字符串 #### 数组 - **学习理解**:数组是**连续货架**,链表是**分散仓库**。双指针技巧: - 快慢指针 → 环形检测(Floyd判圈) - 滑动窗口 → 最长无重复子串 - **高频面试答案**: **题**:如何在O(n)时间O(1)空间移除有序数组重复项? **答案**:双指针(慢指针存唯一位置): ```java int removeDuplicates(int[] nums) { int slow = 0; for (int fast = 1; fast < nums.length; fast++) { if (nums[fast] != nums[slow]) nums[++slow] = nums[fast]; } return slow + 1; } ``` **实战经验**:在物联网设备数据清洗中,处理亿级传感器数据流,内存占用降低60%。 #### 链表 - **高频面试答案**: **题**:如何检测链表环并找到入口? **答案**: 1. 快慢指针相遇 → 有环 2. 相遇后慢指针回起点,同速前进 → 再次相遇点为入口 **数学证明**:设环外长a,环内相遇点距入口b,剩余c,则2(a+b) = a + b + k(b+c) → a = (k-1)(b+c) + c **实战经验**:在分布式任务调度中,检测任务依赖环(有向图判环算法基础)。 --- ### 三、栈、队列与哈希表 #### 单调栈 - **学习理解**:单调栈是**登山缆车**(只保留更高元素) - **高频面试答案**: **题**:如何O(n)求解"每日温度"(下一个更高气温天数)? **答案**:维护温度递减栈: ```java int[] dailyTemperatures(int[] temps) { Stack<Integer> stack = new Stack<>(); int[] res = new int[temps.length]; for (int i = 0; i < temps.length; i++) { while (!stack.isEmpty() && temps[i] > temps[stack.peek()]) { int idx = stack.pop(); res[idx] = i - idx; // 等待天数 } stack.push(i); } return res; } ``` **实战经验**:在股票交易系统预测价格突破点,替代O(n²)暴力解。 #### 哈希表 - **高频面试答案**: **题**:如何设计防哈希碰撞攻击的HashMap? **答案**: 1. **动态扩容**:负载因子>0.75时扩容2倍 2. **链表转红黑树**:JDK8优化,桶长度>8时转换 3. **优质哈希函数**:如String的`31 * hash + char`(质数减少碰撞) **实战经验**:在API网关中,对用户ID设计哈希盐(Salt)防止DoS攻击。 --- ### 四、树形数据结构 #### 红黑树 - **学习理解**:红黑树是**平衡的二叉搜索树**,特性口诀: - 根叶黑(Root and leaves black) - 红子黑(Red node has black children) - 黑同高(All paths have same black height) - **高频面试答案**: **题**:红黑树 vs AVL树适用场景? **答案**: | **场景** | **选择** | |------------------|------------| | 频繁查询(如DB索引) | AVL(更严格平衡) | | 频繁增删(如Java HashMap) | 红黑树(旋转次数少)| **实战经验**:在文件系统索引中,B+树(红黑树变种)实现百万文件快速检索。 #### 堆 - **高频面试答案**: **题**:如何O(n)建堆? **答案**:从最后一个非叶子节点开始**下沉调整**(Heapify): ```java void buildHeap(int[] arr) { for (int i = arr.length / 2 - 1; i >= 0; i--) heapify(arr, i, arr.length); } void heapify(int[] arr, int i, int n) { int largest = i, left = 2 * i + 1, right = 2 * i + 2; if (left < n && arr[left] > arr[largest]) largest = left; if (right < n && arr[right] > arr[largest]) largest = right; if (largest != i) { swap(arr, i, largest); heapify(arr, largest, n); } } ``` **实战经验**:在实时推荐系统,堆维护Top K热门商品(避免全排序O(n logn))。 --- ### 五、图论算法 #### Dijkstra算法 - **学习理解**:Dijkstra是**贪心版BFS**,适用非负权图(GPS导航)。 - **高频面试答案**: **题**:为什么Dijkstra不能处理负权边? **答案**:贪心策略假设**当前最短即全局最短**,但负权边可能使已确定路径变短。 **替代方案**:Bellman-Ford(O(VE))或SPFA算法。 **实战经验**:在物流路径规划中,预处理移除负权边(如补贴路线)。 #### 并查集 - **高频面试答案**: **题**:朋友圈题(连通分量)如何用并查集优化? **答案**:**路径压缩+按秩合并**使操作接近O(α(n))(阿克曼反函数): ```java int find(int x) { if (parent[x] != x) parent[x] = find(parent[x]); // 路径压缩 return parent[x]; } void union(int x, int y) { int rx = find(x), ry = find(y); if (rank[rx] > rank[ry]) parent[ry] = rx; else { parent[rx] = ry; if (rank[rx] == rank[ry]) rank[ry]++; } } ``` **实战经验**:在社交网络分析中,10亿关系计算连通分量,耗时从小时级降至分钟级。 --- ### 六、排序与搜索算法 #### 外部排序 - **学习理解**:外部排序是**分治+归并**,解决内存不足题。 - **高频面试答案**: **题**:如何对100GB日志文件排序? **答案**: 1. **分块**:按内存大小切分成排序的临时文件 2. **归并**:多路归并(堆维护最小值)写回结果 **优化**:置换选择排序生成更长有序段。 **实战经验**:在数仓ETL过程,10路归并处理TB级用户行为数据。 #### 二分查找 - **高频面试答案**: **题**:旋转排序数组搜索(如[4,5,6,7,0,1,2]找0)? **答案**:判断mid左右有序性: ```java int search(int[] nums, int target) { int left = 0, right = nums.length - 1; while (left <= right) { int mid = left + (right - left) / 2; if (nums[mid] == target) return mid; if (nums[left] <= nums[mid]) { // 左半有序 if (nums[left] <= target && target < nums[mid]) right = mid - 1; else left = mid + 1; } else { // 右半有序 if (nums[mid] < target && target <= nums[right]) left = mid + 1; else right = mid - 1; } } return -1; } ``` **实战经验**:在日志时间戳检索中,比线性搜索快1000倍。 --- ### 七、动态规划 #### 背包题 - **学习理解**:DP三要素 → **状态定义、转移方程、初始化**。 - **高频面试答案**: **题**:0-1背包空间如何从O(nW)优化到O(W)? **答案**:**倒序更新一维数组**(避免覆盖前一状态): ```java int knapsack(int[] weights, int[] values, int W) { int[] dp = new int[W + 1]; for (int i = 1; i <= weights.length; i++) for (int j = W; j >= weights[i - 1]; j--) // 反向遍历 dp[j] = Math.max(dp[j], dp[j - weights[i - 1]] + values[i - 1]); return dp[W]; } ``` **实战经验**:在资源调度系统,决策最优任务组合(价值最大化),处理10⁵级任务。 #### 编辑距离 - **高频面试答案**: **题**:字符串"kitten"→"sitting"最小操作数? **答案**:DP定义`dp[i][j]`为子串s1[0:i]到s2[0:j]的编辑距离: ``` 状态转移: if (s1[i] == s2[j]) dp[i][j] = dp[i-1][j-1] else dp[i][j] = min( dp[i-1][j] + 1, // 删除 dp[i][j-1] + 1, // 插入 dp[i-1][j-1] + 1 // 替换 ) ``` **实战经验**:在智能客服纠错模块,改进用户输入准确率30%。 --- ### 八、贪心算法 #### 区间调度 - **学习理解**:贪心选择 → **最早结束区间**(给后续留更多时间)。 - **高频面试答案**: **题**:最多不重叠会议安排? **答案**:按结束时间排序,遍历选择不冲突会议: ```java int maxMeetings(int[][] intervals) { Arrays.sort(intervals, (a, b) -> a[1] - b[1]); int count = 1, end = intervals[0][1]; for (int i = 1; i < intervals.length; i++) { if (intervals[i][0] >= end) { count++; end = intervals[i][1]; } } return count; } ``` **实战经验**:在会议室预订系统,优化资源利用率提升40%。 --- ### 九、高级数据结构 #### 布隆过滤器 - **学习理解**:布隆过滤器是**概率型哈希表**,特性: - 存在 → **可能误判** - 不存在 → **绝对正确** - **高频面试答案**: **题**:如何降低布隆过滤器误判率? **答案**:增加哈希函数k和位数组大小m,公式: ``` m = - (n * ln(p)) / (ln2)^2 (n:元素数量, p:期望误判率) k = (m / n) * ln2 ``` **实战经验**:在分布式缓存穿透防护,拦截99.9%恶意查询,降低DB压力。 --- ### 十、实战技巧 #### LRU缓存设计 - **高频面试答案**: **题**:如何实现O(1)的LRU缓存? **答案**:**哈希表(快速查找) + 双向链表(维护顺序)**: ```java class LRUCache { class Node { int key, value; Node prev, next; } Map<Integer, Node> cache = new HashMap<>(); Node head = new Node(), tail = new Node(); int capacity; public void addNode(Node node) { node.prev = head; node.next = head.next; head.next.prev = node; head.next = node; } public void removeNode(Node node) { node.prev.next = node.next; node.next.prev = node.prev; } public int get(int key) { if (!cache.containsKey(key)) return -1; Node node = cache.get(key); removeNode(node); addNode(node); return node.value; } } ``` **实战经验**:在分布式缓存系统,千万级QPS下命中率提升至95%。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值