MySQL高级篇——关联查询和子查询优化

news2024/11/27 10:14:08

导航:

【黑马Java笔记+踩坑汇总】Java基础+进阶+JavaWeb+SSM+SpringBoot+瑞吉外卖+SpringCloud+黑马旅游+谷粒商城+学成在线+设计模式+牛客面试题

目录

1. 关联查询优化

1.0 优化方案

1.1 数据准备

1.2 左外连接:优先右表创建索引,连接字段类型要一致

1.3 内连接:驱动表由数据量和索引决定

1.4 join语句原理

2. 子查询优化:拆开查询或优化成连接查询


 

1. 关联查询优化

1.0 优化方案

  • 外连接小表驱动大表:LEFT JOIN 时,选择小表作为驱动表, 大表作为被驱动表 。减少外层循环的次数。
  • 内连接驱动表由优化器决定:INNER JOIN 时,MySQL会自动将 小结果集的表选为驱动表 。选择相信MySQL优化策略。
  • 被驱动表优先创建索引:被驱动表的JOIN字段要创建索引;
  • 两表连接字段类型必须一致:两个表JOIN字段数据类型保持绝对一致。防止自动类型转换导致索引失效。
  • 关联替代子查询:能够直接多表关联的尽量直接关联,不用子查询。(减少查询的趟数)。子查询是一个SELECT查询的结果作为另一个SELECT语句的条件。
  • 多次查询代替子查询:不建议使用子查询,建议将子查询SQL拆开结合程序多次查询,或使用 JOIN 来代替子查询。
  • 衍生表建不了索引

1.1 数据准备

# 分类
CREATE TABLE IF NOT EXISTS `type` (
`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
`card` INT(10) UNSIGNED NOT NULL,
PRIMARY KEY (`id`)
);
#图书
CREATE TABLE IF NOT EXISTS `book` (
`bookid` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
`card` INT(10) UNSIGNED NOT NULL,
PRIMARY KEY (`bookid`)
);

#向分类表中添加20条记录
INSERT INTO `type`(card) VALUES(FLOOR(1 + (RAND() * 20)));
INSERT INTO `type`(card) VALUES(FLOOR(1 + (RAND() * 20)));
INSERT INTO `type`(card) VALUES(FLOOR(1 + (RAND() * 20)));
INSERT INTO `type`(card) VALUES(FLOOR(1 + (RAND() * 20)));
INSERT INTO `type`(card) VALUES(FLOOR(1 + (RAND() * 20)));
INSERT INTO `type`(card) VALUES(FLOOR(1 + (RAND() * 20)));
INSERT INTO `type`(card) VALUES(FLOOR(1 + (RAND() * 20)));
INSERT INTO `type`(card) VALUES(FLOOR(1 + (RAND() * 20)));
INSERT INTO `type`(card) VALUES(FLOOR(1 + (RAND() * 20)));
INSERT INTO `type`(card) VALUES(FLOOR(1 + (RAND() * 20)));
INSERT INTO `type`(card) VALUES(FLOOR(1 + (RAND() * 20)));
INSERT INTO `type`(card) VALUES(FLOOR(1 + (RAND() * 20)));
INSERT INTO `type`(card) VALUES(FLOOR(1 + (RAND() * 20)));
INSERT INTO `type`(card) VALUES(FLOOR(1 + (RAND() * 20)));
INSERT INTO `type`(card) VALUES(FLOOR(1 + (RAND() * 20)));
INSERT INTO `type`(card) VALUES(FLOOR(1 + (RAND() * 20)));
INSERT INTO `type`(card) VALUES(FLOOR(1 + (RAND() * 20)));
INSERT INTO `type`(card) VALUES(FLOOR(1 + (RAND() * 20)));
INSERT INTO `type`(card) VALUES(FLOOR(1 + (RAND() * 20)));
INSERT INTO `type`(card) VALUES(FLOOR(1 + (RAND() * 20)));

#向图书表中添加20条记录
INSERT INTO book(card) VALUES(FLOOR(1 + (RAND() * 20)));
INSERT INTO book(card) VALUES(FLOOR(1 + (RAND() * 20)));
INSERT INTO book(card) VALUES(FLOOR(1 + (RAND() * 20)));
INSERT INTO book(card) VALUES(FLOOR(1 + (RAND() * 20)));
INSERT INTO book(card) VALUES(FLOOR(1 + (RAND() * 20)));
INSERT INTO book(card) VALUES(FLOOR(1 + (RAND() * 20)));
INSERT INTO book(card) VALUES(FLOOR(1 + (RAND() * 20)));
INSERT INTO book(card) VALUES(FLOOR(1 + (RAND() * 20)));
INSERT INTO book(card) VALUES(FLOOR(1 + (RAND() * 20)));
INSERT INTO book(card) VALUES(FLOOR(1 + (RAND() * 20)));
INSERT INTO book(card) VALUES(FLOOR(1 + (RAND() * 20)));
INSERT INTO book(card) VALUES(FLOOR(1 + (RAND() * 20)));
INSERT INTO book(card) VALUES(FLOOR(1 + (RAND() * 20)));
INSERT INTO book(card) VALUES(FLOOR(1 + (RAND() * 20)));
INSERT INTO book(card) VALUES(FLOOR(1 + (RAND() * 20)));
INSERT INTO book(card) VALUES(FLOOR(1 + (RAND() * 20)));
INSERT INTO book(card) VALUES(FLOOR(1 + (RAND() * 20)));
INSERT INTO book(card) VALUES(FLOOR(1 + (RAND() * 20)));
INSERT INTO book(card) VALUES(FLOOR(1 + (RAND() * 20)));
INSERT INTO book(card) VALUES(FLOOR(1 + (RAND() * 20)));

1.2 左外连接:优先右表创建索引,连接字段类型要一致

优先右表创建索引:因为左表是查所有数据,右表是按条件查询,所以右表的条件字段创建索引价值更高一点。

连接字段类型要一致:两个表的card字段一定要是同一类型,如果类型不同会导致隐式类型转换从而索引失效。 

验证:

 EXPLAIN 分析左外连接

EXPLAIN SELECT SQL_NO_CACHE * FROM `type` LEFT JOIN book ON type.card = book.card;

结论:type 有All,全表扫描。

右表创建索引优化:

#ALTER TABLE book ADD INDEX Y ( card); #【被驱动表】,可以避免全表扫描
CREATE INDEX Y ON book(card);
EXPLAIN SELECT SQL_NO_CACHE * FROM `type` LEFT JOIN book ON type.card = book.card;

可以看到第二行的 type 变为了 ref,rows 也变成了优化比较明显。这是由左连接特性决定的。LEFT JOIN 条件用于确定如何从右表搜索行,左边一定都有,所以 右边是我们的关键点,一定需要建立索引

表创建索引优化:

ALTER TABLE `type` ADD INDEX X (card); #【驱动表】,无法避免全表扫描
EXPLAIN SELECT SQL_NO_CACHE * FROM `type` LEFT JOIN book ON type.card = book.card;

接着:

DROP INDEX Y ON book;
EXPLAIN SELECT SQL_NO_CACHE * FROM `type` LEFT JOIN book ON type.card = book.card;

1.3 内连接:驱动表由数据量和索引决定

内连接查到的是交集,两个表谁做驱动表查的结果是一样的。所以查询优化器会根据查询成本选择驱动表。驱动表就是主表,被驱动表就是从表

驱动表的选择依据:

  • 没索引的表:当只有一个表有索引时,查询优化器会选择没索引的表作为驱动表。
  • 小表:当两个表都有或都没有索引时,数据量小的表为驱动表。

验证:

drop index X on type;
drop index Y on book;(如果已经删除了可以不用再执行该操作)

 inner join不加索引(MySQL自动选择驱动表)

EXPLAIN SELECT SQL_NO_CACHE * FROM type INNER JOIN book ON type.card=book.card;

book表添加索引优化,可以看到被驱动表是book表:

ALTER TABLE book ADD INDEX Y (card);
EXPLAIN SELECT SQL_NO_CACHE * FROM type INNER JOIN book ON type.card=book.card;

 

type表添加索引, 可以看到被驱动表是type表:

ALTER TABLE type ADD INDEX X (card);
EXPLAIN SELECT SQL_NO_CACHE * FROM type INNER JOIN book ON type.card=book.card;

对于内连接来说,查询优化器可以决定谁作为驱动表,谁作为被驱动表出现的

删除type表索引,发现

DROP INDEX X ON `type`;
EXPLAIN SELECT SQL_NO_CACHE * FROM TYPE INNER JOIN book ON type.card=book.card;

接着:

ALTER TABLE `type` ADD INDEX X (card);
EXPLAIN SELECT SQL_NO_CACHE * FROM `type` INNER JOIN book ON type.card=book.card;

接着:

#向图书表中添加20条记录
INSERT INTO book(card) VALUES(FLOOR(1 + (RAND() * 20)));
INSERT INTO book(card) VALUES(FLOOR(1 + (RAND() * 20)));
INSERT INTO book(card) VALUES(FLOOR(1 + (RAND() * 20)));
INSERT INTO book(card) VALUES(FLOOR(1 + (RAND() * 20)));
INSERT INTO book(card) VALUES(FLOOR(1 + (RAND() * 20)));
INSERT INTO book(card) VALUES(FLOOR(1 + (RAND() * 20)));
INSERT INTO book(card) VALUES(FLOOR(1 + (RAND() * 20)));
INSERT INTO book(card) VALUES(FLOOR(1 + (RAND() * 20)));
INSERT INTO book(card) VALUES(FLOOR(1 + (RAND() * 20)));
INSERT INTO book(card) VALUES(FLOOR(1 + (RAND() * 20)));
INSERT INTO book(card) VALUES(FLOOR(1 + (RAND() * 20)));
INSERT INTO book(card) VALUES(FLOOR(1 + (RAND() * 20)));
INSERT INTO book(card) VALUES(FLOOR(1 + (RAND() * 20)));
INSERT INTO book(card) VALUES(FLOOR(1 + (RAND() * 20)));
INSERT INTO book(card) VALUES(FLOOR(1 + (RAND() * 20)));
INSERT INTO book(card) VALUES(FLOOR(1 + (RAND() * 20)));
INSERT INTO book(card) VALUES(FLOOR(1 + (RAND() * 20)));
INSERT INTO book(card) VALUES(FLOOR(1 + (RAND() * 20)));
INSERT INTO book(card) VALUES(FLOOR(1 + (RAND() * 20)));
INSERT INTO book(card) VALUES(FLOOR(1 + (RAND() * 20)));

ALTER TABLE book ADD INDEX Y (card);
EXPLAIN SELECT SQL_NO_CACHE * FROM `type` INNER JOIN book ON `type`.card = book.card;

图中发现,由于type表数据大于book表数据,MySQL选择将type作为被驱动表。

 

1.4 join语句原理

join方式连接多个表,本质就是各个表之间数据的循环匹配。MySQL5.5版本之前,MySQL只支持一种表间关联方式,就是嵌套循环(Nested Loop Join)。如果关联表的数据量很大,则join关联的执行时间会很长。在MySQL5.5以后的版本中,MySQL通过引入BNLJ算法来优化嵌套执行。

1. 驱动表和被驱动表

驱动表就是主表,被驱动表就是从表、非驱动表。

  • 对于内连接来说:
SELECT * FROM A JOIN B ON ...

A一定是驱动表吗?不一定,优化器会根据你查询语句做优化,决定先查哪张表。先查询的那张表就是驱动表,反之就是被驱动表。通过explain关键字可以查看。

  • 对于外连接来说:
SELECT * FROM A LEFT JOIN B ON ...
# 或
SELECT * FROM B RIGHT JOIN A ON ... 

通常,大家会认为A就是驱动表,B就是被驱动表。但也未必。测试如下:

CREATE TABLE a(f1 INT, f2 INT, INDEX(f1)) ENGINE=INNODB;
CREATE TABLE b(f1 INT, f2 INT) ENGINE=INNODB;

INSERT INTO a VALUES(1,1),(2,2),(3,3),(4,4),(5,5),(6,6);
INSERT INTO b VALUES(3,3),(4,4),(5,5),(6,6),(7,7),(8,8);

SELECT * FROM b;

# 测试1
EXPLAIN SELECT * FROM a LEFT JOIN b ON(a.f1=b.f1) WHERE (a.f2=b.f2);

# 测试2
EXPLAIN SELECT * FROM a LEFT JOIN b ON(a.f1=b.f1) AND (a.f2=b.f2);

2. Simple Nested-Loop Join (简单嵌套循环连接)

算法相当简单,从表A中取出一条数据1,遍历表B,将匹配到的数据放到result.. 以此类推,驱动表A中的每一条记录与被驱动表B的记录进行判断:

可以看到这种方式效率是非常低的,以上述表A数据100条,表B数据1000条计算,则A*B=10万次。开销统计如下:

开销统计SNLJ
外表扫描次数1
内表扫描次数A
读取记录数A+B * A
JOIN比较次数B * A
回表读取记录次数0

当然mysql肯定不会这么粗暴的去进行表的连接,所以就出现了后面的两种对Nested-Loop Join优化算法。

3. Index Nested-Loop Join (索引嵌套循环连接)

Index Nested-Loop Join其优化的思路主要是为了减少内存表数据的匹配次数,所以要求被驱动表上必须有索引才行。通过外层表匹配条件直接与内层表索引进行匹配,避免和内存表的每条记录去进行比较,这样极大的减少了对内存表的匹配次数。

驱动表中的每条记录通过被驱动表的索引进行访问,因为索引查询的成本是比较固定的,故mysql优化器都倾向于使用记录数少的表作为驱动表(外表)。

如果被驱动表加索引,效率是非常高的,但如果索引不是主键索引,所以还得进行一次回表查询。相比,被驱动表的索引是主键索引,效率会更高。

4. Block Nested-Loop Join(块嵌套循环连接)

注意:

这里缓存的不只是关联表的列,select后面的列也会缓存起来。

在一个有N个join关联的sql中会分配N-1个join buffer。所以查询的时候尽量减少不必要的字段,可以让join buffer中可以存放更多的列。

参数设置:

  • block_nested_loop

通过show variables like '%optimizer_switch% 查看 block_nested_loop状态。默认是开启的。

  • join_buffer_size

驱动表能不能一次加载完,要看join buffer能不能存储所有的数据,默认情况下join_buffer_size=256k

mysql> show variables like '%join_buffer%';

join_buffer_size的最大值在32位操作系统可以申请4G,而在64位操作系统下可以申请大于4G的Join Buffer空间(64位Windows除外,其大值会被截断为4GB并发出警告)。

5. Join小结

1、整体效率比较:INLJ > BNLJ > SNLJ

2、永远用小结果集驱动大结果集(其本质就是减少外层循环的数据数量)(小的度量单位指的是表行数 * 每行大小)

select t1.b,t2.* from t1 straight_join t2 on (t1.b=t2.b) where t2.id<=100; # 推荐
select t1.b,t2.* from t2 straight_join t1 on (t1.b=t2.b) where t2.id<=100; # 不推荐

3、为被驱动表匹配的条件增加索引(减少内存表的循环匹配次数)

4、增大join buffer size的大小(一次索引的数据越多,那么内层包的扫描次数就越少)

5、减少驱动表不必要的字段查询(字段越少,join buffer所缓存的数据就越多)

6. Hash Join

从MySQL的8.0.20版本开始将废弃BNLJ,因为从MySQL8.0.18版本开始就加入了hash join默认都会使用hash join

  • Nested Loop:

    对于被连接的数据子集较小的情况,Nested Loop是个较好的选择。

  • Hash Join是做大数据集连接时的常用方式,优化器使用两个表中较小(相对较小)的表利用Join Key在内存中建立散列表,然后扫描较大的表并探测散列表,找出与Hash表匹配的行。

    • 这种方式适合于较小的表完全可以放于内存中的情况,这样总成本就是访问两个表的成本之和。
    • 在表很大的情况下并不能完全放入内存,这时优化器会将它分割成若干不同的分区,不能放入内存的部分就把该分区写入磁盘的临时段,此时要求有较大的临时段从而尽量提高I/O的性能。
    • 它能够很好的工作于没有索引的大表和并行查询的环境中,并提供最好的性能。大多数人都说它是Join的重型升降机。Hash Join只能应用于等值连接(如WHERE A.COL1 = B.COL2),这是由Hash的特点决定的。

2. 子查询优化:拆开查询或优化成连接查询

MySQL从4.1版本开始支持子查询,使用子查询可以进行SELECT语句的嵌套查询,即一个SELECT查询的结果作为另一个SELECT语句的条件。 子查询可以一次性完成很多逻辑上需要多个步骤才能完成的SQL操作 。

子查询是 MySQL 的一项重要的功能,可以帮助我们通过一个 SQL 语句实现比较复杂的查询。但是,子查询的执行效率不高。原因:

① 执行子查询时,MySQL需要为内层查询语句的查询结果建立一个临时表 ,然后外层查询语句从临时表中查询记录。查询完毕后,再撤销这些临时表 。这样会消耗过多的CPU和IO资源,产生大量的慢查询。

② 子查询的结果集存储的临时表,不论是内存临时表还是磁盘临时表都 不会存在索引 ,所以查询性能会 受到一定的影响。

③ 对于返回结果集比较大的子查询,其对查询性能的影响也就越大。

在MySQL中,可以使用连接(JOIN)查询来替代子查询。连接查询 不需要建立临时表 ,其 速度比子查询 要快 ,如果查询中使用索引的话,性能就会更好。

举例1:查询学生表中是班长的学生信息

  • 使用子查询
# 创建班级表中班长的索引
CREATE INDEX idx_monitor ON class(monitor);

EXPLAIN SELECT * FROM student stu1
WHERE stu1.`stuno` IN (
SELECT monitor
FROM class c
WHERE monitor IS NOT NULL
)
  • 推荐使用多表查询
EXPLAIN SELECT stu1.* FROM student stu1 JOIN class c
ON stu1.`stuno` = c.`monitor`
WHERE c.`monitor` is NOT NULL;

举例2:取所有不为班长的同学

  • 不推荐
EXPLAIN SELECT SQL_NO_CACHE a.*
FROM student a
WHERE a.stuno NOT IN (
    SELECT monitor FROM class b
    WHERE monitor IS NOT NULL
);

执行结果如下:

  • 推荐:
EXPLAIN SELECT SQL_NO_CACHE a.*
FROM student a LEFT OUTER JOIN class b
ON a.stuno = b.monitor
WHERE b.monitor IS NULL;

结论:尽量不要使用NOT IN或者NOT EXISTS,用LEFT JOIN xxx ON xx WHERE xx IS NULL替代

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/553286.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

numpy-stl实战3D建模【Python】

想象一下&#xff0c;我们需要用 python 编程语言构建某个物体的三维模型&#xff0c;然后将其可视化&#xff0c;或者准备一个文件以便在 3D 打印机上打印。 有几个库可以解决这些问题。 让我们来看看&#xff0c;如何在 Python 中从点、边和图元构建 3D 模型。 如何执行基本的…

如何对图片进行卷积计算

1 问题 如何对图片进行卷积计算&#xff1f; 2 方法 先导入torch和torch里的nn类&#xff0c;然后设置一个指定尺寸的随机像素值的图片&#xff0c;然后使用nn.conv2d函数进行卷积计算&#xff0c;然后建立全连接层&#xff0c;最后得到新的图片的尺寸 步骤: (1) 导入实验所需要…

CyberLink的音频编辑软件AudioDirector Ultra 13.4版本在win10系统的下载与安装配置教程

目录 前言一、AudioDirector Ultra安装二、使用配置总结 前言 AudioDirector Ultra是由CyberLink公司开发的一款强大的音频编辑工具&#xff0c;旨在为用户提供全面的音频后期制作和编辑解决方案。该软件支持多种音频格式&#xff0c;包括MP3、WAV、M4A等&#xff0c;并且可以…

网络工程师精选习题详解(二)

请点击↑关注、收藏&#xff0c;本博客免费为你获取精彩知识分享&#xff01;有惊喜哟&#xff01;&#xff01; 201.通常使用&#xff08;&#xff09;为IP数据报进行加密。 A.IPSec B.PP2P C.HTTPS D.TLS 答案&#xff1a;A IP Sec可以为IP数据报进行加密。 …

【004hive基础】hive的文件存储格式与压缩

文章目录 一.hive的行式存储与列式存储二. 存储格式1. TEXTFILE2. ORC格式3. PARQUET格式 ing 三. Hive压缩格式1. mr支持的压缩格式:2. hive配置压缩的方式:2.1. 开启map端的压缩方式:2.2.开启reduce端的压缩方式: 四. hive中存储格式和压缩相结合五. hive主流存储格式性能对比…

【分立元件】MOSFET的工作原理

MOSFET适用于瓦至十数千瓦的中小功率,特别适用于电源管理行业的入门学习。IGBT和MOSFET使用相似,但属于中大功率场合才使用,如果想使用好IGBT,也要先学习MOSFET。 对于MOSFET的学习我们需要学习它的工作原理,知道MOSFET的主要参数,MOSFET的开关过程以及如何驱动MOSFET,应…

技术最强,干活最多,但不会来事,又不是嫡系,得不到领导重用,这种情况去创业公司会不会好点?...

能力强但情商不高&#xff0c;许多程序员都有这样的问题&#xff0c;这种情况怎么办&#xff1f; 一位程序员问&#xff1a; 组内技术能力最强&#xff0c;干活最多&#xff0c;解决不了的问题就会派他上&#xff0c;领导嘴上认可&#xff0c;但因为他不会来事&#xff0c;又不…

一文搞定十大排序算法

文章目录 概述冒泡排序 (Bubble Sort)算法步骤图解算法代码实现算法分析 选择排序 (Selection Sort)算法步骤算法图解代码实现算法分析 插入排序(Insertion Sort)算法步骤图解算法代码实现算法分析 希尔排序 (Shell Sort)算法步骤图解算法代码实现算法分析 归并排序 (Merge Sor…

多维时序 | MATLAB实现GA-LSTM遗传算法优化长短期记忆网络的多变量时间序列预测

多维时序 | MATLAB实现GA-LSTM遗传算法优化长短期记忆网络的多变量时间序列预测 目录 多维时序 | MATLAB实现GA-LSTM遗传算法优化长短期记忆网络的多变量时间序列预测效果一览基本介绍程序设计参考资料 效果一览 基本介绍 MATLAB实现GA-LSTM遗传算法优化长短期记忆网络的数据多…

系统集成实验模拟总公司和分公司之间通信(涉及mpls vxn,链路聚合,nat,vlan划分,单臂路由,dhcp....)

目录 一 需求描述 二 需求分析 三 实验拓扑 四 实验配置 4.1 总公司 4.1.1 vlan间通信 4.1.2 dhcp自动分配ip 配置地址池 接口开启dhcp 4.1.3 链路聚合 4.1.4 ospf实现内网通信 4.2 分公司 4.2.1 单臂路由 4.2.2 dhcp自动获取ip 4.2.3 ospf实现内网通信 4.3 mp…

判断传入数据是否为列表、数组、数据框等数据结构pd.api.types.is_list_like()

【小白从小学Python、C、Java】 【计算机等考500强证书考研】 【Python-数据分析】 判断传入数据是否为 列表、数组、数据框等数据结构 pd.api.types.is_list_like() 选择题 下列说法错误的是? import pandas as pd import numpy as np print("【执行】pd.api.ty…

基于html+css的图展示85

准备项目 项目开发工具 Visual Studio Code 1.44.2 版本: 1.44.2 提交: ff915844119ce9485abfe8aa9076ec76b5300ddd 日期: 2020-04-16T16:36:23.138Z Electron: 7.1.11 Chrome: 78.0.3904.130 Node.js: 12.8.1 V8: 7.8.279.23-electron.0 OS: Windows_NT x64 10.0.19044 项目…

深度学习之使用Keras构建分类问题的MLP神经网络——用于糖尿病预测

大家好&#xff0c;我是带我去滑雪&#xff01; Keras 是一个用于构建和训练深度学习模型的高级 API&#xff0c;它基于 Python编写&#xff0c;并能够运行于 TensorFlow, CNTK, 或者 Theano 等深度学习框架之上。Keras简化了深度神经网络的构建流程&#xff0c;让用户能够更加…

云计算基础——云计算主流解决方案

原数据&#xff1a;描述数据的数据&#xff0c;不可分割。 7.1 Google云计算技术 7.1.1 GCP Google 将这些技术组合在一起&#xff0c;运用这些从自身业务需求出发&#xff0c;逐步发展起来的一系列云计算技术和工具搭建起了其面向商业的云计算解决方案Google Cloud Platform (…

【数据湖架构】Azure Data Lake数据湖指南

数据湖漫游指南 文件大小和文件数文件格式分区方案使用查询加速我如何管理对我的数据的访问&#xff1f;我选择什么数据格式&#xff1f;如何管理我的数据湖成本&#xff1f;如何监控我的数据湖&#xff1f;ADLS Gen2 何时是您数据湖的正确选择&#xff1f;设计数据湖的关键考虑…

Vue.observable的理解

一、Observable 是什么 Observable 翻译过来我们可以理解成可观察的 先来看其在Vue中的定义 Vue.observable&#xff0c;让一个对象变成响应式数据。Vue 内部会用它来处理 data 函数返回的对象 返回的对象可以直接用于渲染函数和计算属性内&#xff0c;并且会在发生变更时触发…

PDF.js实现按需分片加载pdf文件-包含前后端开发源码和详细开发教程

PDF.js实现按需加载pdf文件 说明前言前端项目分片加载的效果前端项目结构前端核心代码项目运行与访问 后端项目项目结构核心代码实现注意事项 项目源码 说明 本文主要是介绍pdf.js的前后端项目的实现&#xff0c;包含可直接运行的源码。由于本人偏向于后端开发&#xff0c;因此…

Redis设计逻辑及生产部署问题整理

数据结构 redis数据结构包括&#xff1a;简单动态字符串SDS、链表、字典、跳跃表、整数组合、压缩列表。 SDS&#xff1a;在增加/减少字符串时不会频繁进行内存充分配&#xff0c;采用了空间预分配和惰性空间释放两种优化策略。 链表&#xff1a;链表节点使用void*保存节点值&a…

Stable Diffusion Web-UI 安装指南

Stable DIffusion 是 Stability.AI 开源的 text-to-image 模型&#xff0c;目前类似产品有 Midjourney 以及 OpenAI 的 DELL-2 &#xff1b;从AI绘画效果上来说&#xff0c;Midjourney 目前公认是最好的&#xff1b;但从模型的可玩性和发展潜力来看&#xff0c;个人观点来看&am…

【009】C++数据类型之转义字符和类型转换

C数据类型之转义字符和类型转换 引言一、转义字符1.1、概念1.2、八进制转义1.3、十六进制转义 二、类型转换2.1、自动类型转换原则2.2、强制类型转换 三、C新特性中类型转换的扩展3.1、隐式类型转换3.2、显式类型转换 总结 引言 &#x1f4a1; 作者简介&#xff1a;专注于C/C高…