“我明明建了索引,为什么还是全表扫描?”这是 MySQL 优化里最常遇到的问题。索引失效的原因很多,但归根结底就两大类:写法让索引没法用,或者优化器算完账觉得不用更快。本文把两类都拆开讲。
一、先搞懂 InnoDB 的索引结构不理解 B+Tree,就记不住那些失效规则,只能死记硬背。
1.1 为什么是 B+Tree 而不是 BTree
对比项
BTree
B+Tree
数据存储位置
每个节点都存数据
只有叶子节点存数据
叶子节点连接
无
有双向链表相连
单点查询性能
可能更快(根附近就命中)
稳定,都要走到叶子
范围查询
需要中序遍历
沿链表顺序扫描,极快
非叶子节点容量
小(要存数据)
大(只存键值),树更矮
B+Tree 的优势集中在一句话上:非叶子节点不存数据,所以一个页能装下更多键值,树高更矮,磁盘 IO 次数更少。
粗略估算:InnoDB 默认页大小 16 KB,主键为 bigint(8 字节)+ 指针(6 字节)约 14 字节,一个非叶子页能放约 1170 个键值。
树高 2 层:约 1170 × 16 ≈ 1.8 万行
树高 3 ...
Redis 大多数人都”会用”,但线上事故往往出在选型和边界情况上:一个 KEYS * 拖垮整个实例,一次缓存雪崩打穿数据库。本文不讲安装,只讲生产环境真正会遇到的问题。
一、数据结构怎么选选错数据结构的代价,往往是内存翻几倍、或者用一堆笨拙的组合去模拟本该原生支持的能力。
1.1 五种基础类型对比
类型
底层实现
典型场景
单键建议上限
String
SDS 动态字符串
缓存、计数器、分布式锁、Session
值不超过 10 KB
Hash
压缩列表 / 哈希表
对象存储(购物车、用户资料)
field 不超过 1000
List
快速链表
消息队列、最新列表、粉丝列表
元素不超过 1 万
Set
哈希表 / 整数集合
去重、标签、共同好友、抽奖
元素不超过 1 万
ZSet
跳表 + 哈希表
排行榜、延迟队列、优先级队列
元素不超过 1 万
1.2 容易被忽略的选型细节String 存对象 vs Hash 存对象很多人图省事直接把对象序列化成 JSON 塞进 String:
1SET user:1001 '{"n ...
用过 Spring Boot 的人都知道”引入依赖就能用”,但一旦要自己封装一个公共组件给团队复用,就必须搞懂自动装配。本文从源码层面拆开 @SpringBootApplication,然后带你手写一个能放进生产环境的 Starter。
一、自动装配到底做了什么1.1 从 @SpringBootApplication 拆起每个 Spring Boot 项目的启动类上都挂着这么一个注解:
123456@SpringBootApplicationpublic class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); }}
它其实是一个”三合一”的组合注解,扒开源码能看到:
12345678@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)@SpringBootConfiguration ...
经验分享
未读下载node.js点击此处下载结果如下图:
双击点击下载的pkg[根据下图步骤依次点击即可]
选择合适的存储位置安装完成之后检验是否成功
黑窗口输入node -v
Spring Boot 是 Spring 生态的一站式解决方案,通过”约定优于配置”的理念,极大简化了 Spring 应用的搭建和开发过程。本文基于 Spring Boot 3.x 版本,带你从零快速上手。
一、环境准备1.1 版本要求Spring Boot 3.x 对环境有明确要求:
JDK:必须使用 Java 17 及以上版本(推荐 Java 17 LTS 或 Java 21 LTS)
Maven:3.6.3 及以上
Gradle:7.x 及以上
Servlet 容器:Tomcat 10+(Jakarta EE 9+)
1.2 创建项目的三种方式方式一:Spring Initializr(推荐)访问 https://start.spring.io,在线生成项目骨架:
选择 Project(Maven/Gradle)
选择 Language(Java)
选择 Spring Boot 版本
填写 Group、Artifact 等项目信息
添加依赖(Web、MyBatis、Redis 等)
点击 Generate 下载压缩包
方式二:IDEA 创建IntelliJ IDEA 内 ...
线程池是Java并发编程中最常用的工具之一,但《阿里巴巴Java开发手册》明确禁止使用Executors创建线程池,必须通过ThreadPoolExecutor的方式手动创建。本文带你彻底搞懂线程池的核心原理。
一、为什么要用线程池1.1 线程创建的开销每次 new Thread 都会涉及:
内存分配:每个线程栈默认占用 1MB 内存
系统调用:需要操作系统内核创建线程
上下文切换:线程调度带来的 CPU 开销
销毁成本:线程执行完后需要 GC 回收
如果频繁创建销毁线程,性能损耗非常大。
1.2 线程池的优势
降低资源消耗:复用已创建的线程,减少创建销毁开销
提高响应速度:任务到达时无需等待线程创建
提高线程可管理性:统一分配、调优和监控
附加功能:提供定时、延迟、并发控制等增强功能
二、ThreadPoolExecutor 七大核心参数123456789public ThreadPoolExecutor( int corePoolSize, // 1. 核心线程数 int maximumPoolSize, // 2. 最大线程数 ...
Java开发
未读垃圾回收(Garbage Collection,简称 GC)是 JVM 最重要的特性之一,也是 Java 面试的必考点。理解 GC 原理不仅能帮你写出更高效的代码,还能在生产环境出现 OOM、CPU 飙高等问题时快速定位根因。
一、JVM 内存区域划分1.1 运行时数据区12345678JVM 运行时数据区├── 线程共享│ ├── 堆(Heap)—— GC 主要工作区域│ └── 方法区(Method Area)—— 元空间└── 线程私有 ├── 虚拟机栈(VM Stack) ├── 本地方法栈(Native Stack) └── 程序计数器(PC Register)
1.2 堆内存分代模型堆是 GC 的主战场,经典分代模型分为:
123456堆内存(Heap)├── 年轻代(Young Generation)│ ├── Eden 区(8/10)│ ├── Survivor0(1/10)│ └── Survivor1(1/10)└── 老年代(Old Generation)
年轻代:存放新创建的对象,垃圾回收频率高、速度快
老年代:存放存活 ...
Java 8 引入的 Stream API 是 Java 函数式编程的核心利器。配合 Lambda 表达式,可以用声明式的方式处理集合数据,代码更简洁、更易读,还能轻松实现并行计算。本文从入门到实战,带你全面掌握 Stream。
一、Stream 是什么1.1 概念Stream(流)是数据渠道,用于操作数据源(集合、数组等)所生成的元素序列。
特点:
Stream 自己不存储元素,只是对数据进行计算
Stream 操作不会改变源数据,每次操作返回新的 Stream
操作是延迟执行的,只有触发终止操作时才会真正执行
流只能被消费一次,遍历完就用完了
1.2 操作分类1234567Stream 操作├── 中间操作(Intermediate)—— 返回新 Stream,延迟执行│ ├── 无状态:filter、map、flatMap、peek│ └── 有状态:distinct、sorted、limit、skip└── 终止操作(Terminal)—— 触发计算,返回最终结果 ├── 非短路:forEach、collect、reduce、count └── 短路: ...
Linux中nginx的安装首先是系统环境:CentOS7,Nginx版本:1.62(如需其他版本自行到官网下载)
我安装参考的是菜鸟教程的安装方式,附链接:Nginx安装配置
下面是安装教程:
Nginx 安装一、安装编译工具及库文件1yum -y install make zlib zlib-devel gcc-c++ libtool openssl openssl-devel
二、首先要安装 PCREPCRE 作用是让 Nginx 支持 Rewrite 功能。
下载 PCRE 安装包,下载地址: http://downloads.sourceforge.net/project/pcre/pcre/8.35/pcre-8.35.tar.gz12[root@bogon src]# cd /usr/local/src/[root@bogon src]# wget http://downloads.sourceforge.net/project/pcre/pcre/8.35/pcre-8.35.tar.gz
解压安装包:1[root@bogon src]# tar zxvf pcr ...
干货分享
安装完自己的CentOS系统之后,解决连接网络IP频繁变化的问题,在CentOS中设置固定的WiFi IP地址,通常需要编辑网络接口配置文件。以下是一个基于命令行的快速指南:(有线网络和这个操作也大差不差)
找到你的WiFi网络接口名称。1nmcli d
编辑对应的网络配置文件。假设你的WiFi接口名称是wlp3s0,运行:1sudo vi /etc/sysconfig/network-scripts/ifcfg-wlp3s0
修改或添加以下内容:1234567BOOTPROTO=staticONBOOT=yesIPADDR=你的固定IP地址NETMASK=你的子网掩码GATEWAY=你的默认网关DNS1=首选DNS服务器DNS2=备用DNS服务器
重启网络服务:1sudo systemctl restart network
确保替换你的固定IP地址、你的子网掩码、你的默认网关、首选DNS服务器和备用DNS服务器为实际值。以下是一个配置文件的示例:
123456789DEVICE=wlp3s0TYPE=WirelessBOOTPROTO=staticONBOOT= ...













