获得徽章 0
- mysql执行顺序
FROM - 确定涉及的数据源。
ON - 在连接操作中使用,用于指定如何匹配不同表中的行。
JOIN - 如果存在多表连接,则执行相应的连接操作。
WHERE - 应用WHERE子句过滤记录。
GROUP BY - 根据指定的列对数据进行分组。
AGGREGATE FUNCTIONS - 计算每个组的聚合值(如COUNT, SUM等)。
HAVING - 使用HAVING子句进一步过滤分组后的结果。
SELECT - 选取所需的列,并可能包括基于前面步骤计算出的表达式。
DISTINCT - 如果指定了DISTINCT关键字,则移除重复行。
ORDER BY - 排序最终结果集。
LIMIT - 返回指定数量的结果行。展开赞过51 - mysql书写顺序
SELECT - 指定要选择哪些列。
FROM - 指定从哪个表中选择数据。
WHERE - 设置条件以过滤行。
GROUP BY - 将结果集按一个或多个列分组。
HAVING - 对分组后的数据设置条件进行过滤(类似于WHERE子句,但作用于聚合后的数据)。
ORDER BY - 对结果集排序。
LIMIT - 限制返回的结果数量。展开赞过评论1 - 1. 三色标记-清除算法
Go 的垃圾回收器基于三色标记-清除(Mark-and-Sweep)算法进行工作,这个算法可以将所有内存对象分为三类(即三色):
白色:对象还未被标记为可达的,这些对象可能会被清除。
灰色:对象已经被发现并标记为可达,但它的子对象还未被检查。
黑色:对象已经被标记为可达,且它的子对象也都已经被处理。
2. 工作流程
GC 的工作流程通常分为两个阶段:
标记阶段(Mark Phase):从一组根对象(通常是栈、全局变量等)开始,遍历所有可以访问的对象,并将这些对象标记为 "黑色" 或 "灰色",即它们是可达的,不应该被回收。这个阶段的主要工作是从灰色对象开始遍历其子对象,直到所有可达对象都被标记。
清除阶段(Sweep Phase):遍历堆中的所有对象,将未被标记(即白色)的对象回收。被回收的对象将被认为是不可达的,回收其内存空间。
3. 并发垃圾回收
Go 的垃圾回收是 并发 和 分代 的,意味着垃圾回收器能够在程序继续运行的同时执行。具体而言,Go 的 GC 会在后台运行一部分标记工作,而不是在标记时暂停所有 Goroutine 的运行,从而减少停顿时间。展开赞过评论1 - ### 1. Goroutine
- **定义**:Goroutine 是 Go 中轻量级的线程,可以并发地运行函数。每个 Goroutine 的栈大小初始为 2 KB,可以根据需要动态扩展。
- **创建**:通过 `go` 关键字启动 Goroutine,Go 会自动管理它们的生命周期。
### 2. 调度器(Scheduler)
- **角色**:调度器负责在可用的操作系统线程上调度和执行 Goroutine。
- **M:N 模型**:GMP 使用 M:N 模型,将 M 个 Goroutine 映射到 N 个操作系统线程。这意味着多个 Goroutine 可以在单个线程上运行,调度器决定了哪一个 Goroutine 在何时执行。
### 3. 内存管理(M)
- **P(Processor)**:Go 的调度器维护了 P(处理器)概念,每个 P 都代表一个逻辑处理单元。每个 P 维护一个运行队列,存储就绪的 Goroutine。
- **M(Machine)**:M 代表操作系统线程。M 在 P 上运行 Goroutine,Goroutine 在 P 的运行队列中被调度。
### 工作流程
1. **创建 Goroutine**:当创建新的 Goroutine 时,Go 调度器会将其加入当前 P 的运行队列。
2. **调度**:调度器从运行队列中取出 Goroutine,将其分配给空闲的 M 来执行。
3. **Goroutine 切换**:当 Goroutine 阻塞(如等待 I/O 或锁)时,调度器会将其移出 M,并从其他 P 的运行队列中调度其他 Goroutine 进行执行。
### 特性
- **协作式调度**:Goroutine 切换通常是轻量级的,调度器在 Goroutine 阻塞或主动让出控制时进行切换。
- **工作窃取**:调度器实现了工作窃取算法,能够平衡各 P 的负载,确保所有 Goroutine 都能得到执行机会。
### 优势
- **高并发**:通过轻量级的 Goroutine 和高效的调度,Go 能够处理成千上万的并发任务。
- **简单易用**:开发者只需使用 `go` 关键字即可轻松创建 Goroutine,复杂的线程管理和调度由 Go 语言本身负责。展开赞过评论1 - 链表和数组是两种常用的数据结构,各自有其优缺点。以下是它们的比较:
数组
优点:
访问速度快:
数组支持随机访问,通过索引可以在常数时间内访问任意元素。
内存占用紧凑:
数组的元素在内存中是连续存储的,内存占用相对较小,适合处理小规模数据。
简单易用:
数组的使用和实现相对简单,易于理解。
缺点:
大小固定:
一旦创建,数组的大小就不可改变。如果需要增加或减少元素,必须创建新的数组并复制数据。
插入和删除效率低:
在数组中间插入或删除元素需要移动大量元素,时间复杂度为
𝑂
(
𝑛
)
O(n)。
内存浪费:
如果数组大小过大而实际使用的元素较少,会导致内存浪费。
链表
优点:
动态大小:
链表可以动态调整大小,支持在运行时随意增加或减少元素。
插入和删除效率高:
在链表中插入和删除元素只需修改指针,时间复杂度为
𝑂
(
1
)
O(1),前提是已知位置。
无需连续内存:
链表的节点可以分散存储在内存中,避免了数组内存分配的连续性要求。
缺点:
访问速度慢:
链表不支持随机访问,必须从头遍历,访问时间复杂度为
𝑂
(
𝑛
)
O(n)。
额外内存开销:
每个节点需要额外存储指针(或引用),增加了内存开销。
实现复杂性:
链表的实现和维护相对复杂,容易出错(如指针丢失)。
总结
数组适合对大小固定、频繁随机访问的场景,例如图像处理、静态数据存储等。
链表适合需要频繁插入和删除操作的场景,例如实现队列、栈或动态数据集合。
选择数据结构时,需根据具体应用场景的需求进行权衡和决策。展开赞过评论1
![[不看]](http://lf-web-assets.juejin.cn/obj/juejin-web/xitu_juejin_web/img/jj_emoji_102.b113c42.png)
![[奸笑]](http://lf-web-assets.juejin.cn/obj/juejin-web/xitu_juejin_web/img/jj_emoji_17.bcebf79.png)