深入浅出Hive性能优化策略

news2024/11/20 22:38:38

        我们将从基础的HiveQL优化讲起,涵盖数据存储格式选择、数据模型设计、查询执行计划优化等多个方面。会的直接滑到最后看代码和语法。

目录

引言

Hive架构概览

示例1:创建表并加载数据

示例2:优化查询

Hive查询优化

1. 选择适当的文件格式

2. 利用分区和分桶

3. 使用合适的JOIN策略

4. 优化HiveQL语句

Hive参数调优

1. hive.exec.parallel

2.hive.exec.parallel.thread.number

3.hive.exec.dynamic.partition

4.hive.vectorized.execution.enabled

5.mapreduce.job.reduces

6.hive.optimize.sort.dynamic.partition

实践建议

技巧总结


引言

        在当今这个数据驱动的时代,数据已成为企业制胜的关键。众多企业和组织正通过海量数据的分析和处理来挖掘有价值的信息,以支持决策制定,优化业务流程,提升客户体验,甚至开发新的商业模式。在这一背景下,Apache Hive作为一个建立在Hadoop生态系统之上的数据仓库工具,因其能够提供类SQL查询功能而变得极为重要。Hive使得即使是不熟悉Java或MapReduce的数据分析师也能轻松处理大规模数据集。

        Hive的设计初衷是用于数据汇总、查询和分析,但随着数据量的日益增长,性能优化成为了使用Hive时不可或缺的一部分。无论是在数据查询、数据存储格式,还是在执行策略上,Hive都提供了多种优化手段,以满足不同场景下对性能的需求。

        性能优化不仅可以减少资源的浪费,提高查询的响应速度,还能在一定程度上降低计算成本,提升用户体验。优化的过程就像是在寻找最佳路径一样,需要对Hive的内部机制有深入的了解,同时也需要根据实际情况灵活应变,才能找到最适合自己业务场景的优化方案。

        在探索Hive优化策略中,我们将从基础的HiveQL优化讲起,涵盖数据存储格式选择、数据模型设计、查询执行计划优化等多个方面。我们也会讨论如何通过调整Hive配置和使用资源管理器来优化资源利用率,以及如何根据实际的业务需求和数据特性来选择合适的优化手段。

Hive架构概览

        Apache Hive 是一个构建在 Hadoop 生态系统之上的数据仓库软件,用于数据提取、转换和加载(ETL)任务。它提供了一种类似 SQL 的查询语言,称为 HiveQL,让那些熟悉 SQL 的用户可以轻松地进行数据查询和分析。为了更好地理解 Hive 如何进行性能优化,我们首先需要对其架构有一个基本的了解。

Hive 的架构主要包括以下几个组件:

  1. 用户接口:Hive 支持多种用户接口,包括命令行工具(Hive CLI)、Web界面和 JDBC/ODBC 驱动程序。
  2. Hive Server:它允许客户端使用 Thrift 协议远程提交请求到 Hive。
  3. 元数据存储:Hive 使用关系型数据库(如 MySQL、PostgreSQL)存储元数据,包括表的定义、列数据类型、分区信息等。
  4. 执行引擎:Hive 查询最初是通过 MapReduce 执行的,但现在它也支持 Tez 和 Spark 等其他执行引擎,以提高性能。
  5. HDFS:Hive 存储其数据在 Hadoop 分布式文件系统(HDFS)中,利用 HDFS 的高可靠性和高吞吐量。

示例1:创建表并加载数据

为了展示 Hive 的基本用法,我们首先通过一个简单的示例来创建一个 Hive 表,并向其中加载一些数据。

CREATE TABLE IF NOT EXISTS employees (
  id INT,
  name STRING,
  age INT,
  department STRING
)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY ','
STORED AS TEXTFILE;

这段代码创建了一个名为 employees 的表,其中包含 idnameagedepartment 四个字段。字段之间通过逗号分隔。

接下来,我们将数据加载到这个表中。

LOAD DATA LOCAL INPATH '/path/to/employees.txt' INTO TABLE employees;

此命令将本地文件系统中的 employees.txt 文件中的数据加载到 employees 表中。假设该文本文件的每一行都是一个记录,字段之间由逗号分隔。

示例2:优化查询

理解了 Hive 的基础架构后,我们可以通过一些优化技巧来提高查询的性能。假设我们想要查询 department 为 'Sales' 的所有员工,一个未优化的查询可能如下所示:

SELECT * FROM employees WHERE department = 'Sales';

为了优化这个查询,我们可以考虑使用分区。首先,重新创建 employees 表,并按 department 进行分区:

CREATE TABLE employees_partitioned (
  id INT,
  name STRING,
  age INT
)
PARTITIONED BY (department STRING)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY ','
STORED AS TEXTFILE;

然后,我们可以针对特定的 department 分区执行查询,这样 Hive 只需扫描相关的分区数据,而不是整个表:

SELECT * FROM employees_partitioned WHERE department = 'Sales';

通过这种方式,我们可以显著减少查询所需扫描的数据量,从而提高查询效率。

Hive查询优化

        在大数据处理中,编写高效的查询是提高数据处理速度的关键之一。Hive提供了多种方式来优化查询,从而减少执行时间和资源消耗。以下是一些常用的查询优化技巧:

1. 选择适当的文件格式

Hive支持多种文件格式,包括文本文件、SequenceFile、ORC、Parquet等。选择合适的文件格式对于查询性能有显著影响。例如,ORC(Optimized Row Columnar)格式提供了高效的压缩和编码方案,能够显著减少存储空间并加速查询。

示例:

假设我们有一个大型数据集需要频繁查询,我们可以选择ORC格式来存储数据:

CREATE TABLE employees_orc (
  id INT,
  name STRING,
  age INT,
  department STRING
)
STORED AS ORC;

使用ORC格式后,查询同样的数据将更快,因为ORC格式提供了更好的读取性能。

2. 利用分区和分桶

通过将数据分区和分桶,Hive能够更快地定位到查询所需的数据子集,从而减少查询所需扫描的数据量。

示例:

假设我们想要根据部门对员工数据进行分区,并在每个部门内部根据年龄进行分桶:

CREATE TABLE employees_partitioned_bucketed (
  id INT,
  name STRING,
  age INT
)
PARTITIONED BY (department STRING)
CLUSTERED BY (age) INTO 10 BUCKETS
STORED AS ORC;

在这个表中,数据首先按部门进行分区,然后每个部门内的数据根据员工年龄分成10个桶。这样,当执行涉及特定部门和年龄范围的查询时,Hive只需扫描相关的分区和桶,大大提升查询效率。

3. 使用合适的JOIN策略

Hive支持多种JOIN策略,包括MapJoin、SortMergeJoin等。在某些情况下,明确指定JOIN策略可以优化查询性能。

示例:

当我们知道参与JOIN的一个表非常小的时候,可以使用MapJoin来加速处理:

SET hive.auto.convert.join=true;
SET hive.auto.convert.join.noconditionaltask.size=100000;

SELECT /*+ MAPJOIN(small_table) */ *
FROM big_table
JOIN small_table ON big_table.id = small_table.id;

在这个示例中,我们假设small_table的大小足够小,可以完全装载进内存,通过提示Hive使用MapJoin,可以在内存中直接进行JOIN操作,从而加快查询速度。

4. 优化HiveQL语句

编写高效的HiveQL语句也是优化查询的一个重要方面。例如,避免使用SELECT *,而是只选择需要的列,可以减少数据传输和处理的开销。

示例:

-- 不推荐的写法
SELECT * FROM employees WHERE department = 'Sales';

-- 推荐的写法
SELECT id, name FROM employees WHERE department = 'Sales';

在推荐的写法中,我们只选择了idname列,而不是选择所有列,这样可以减少数据的读取和传输量,提高查询效率。

Hive参数调优

Hive的性能不仅取决于查询的写法或数据的存储方式,还受到Hive配置参数的极大影响。正确调整这些参数可以显著提高查询速度和处理效率。下面,我们将探讨一些关键的Hive性能调优参数。

1. hive.exec.parallel

这个参数默认为false,意味着Hive在执行任务时不会并行处理。如果将其设置为true,Hive会尝试并行执行多个任务,这可以显著减少执行时间。

SET hive.exec.parallel = true;

2.hive.exec.parallel.thread.number

当启用并行执行时,此参数控制并行执行的线程数。调整此参数以适应你的集群资源和任务负载。

SET hive.exec.parallel.thread.number = 8;

3.hive.exec.dynamic.partition

此参数用于控制Hive是否启用动态分区。启用动态分区(设置为true)可以在执行插入操作时自动创建分区,这对于处理大量分区非常有用。

SET hive.exec.dynamic.partition = true; 
SET hive.exec.dynamic.partition.mode = nonstrict;

4.hive.vectorized.execution.enabled

启用向量化查询执行可以显著提高查询性能,因为它使得Hive在处理数据批次时能够利用CPU的向量化指令。默认情况下,这个选项可能是关闭的。

SET hive.vectorized.execution.enabled = true; 
SET hive.vectorized.execution.reduce.enabled = true;

5.mapreduce.job.reduces

虽然这是一个MapReduce级别的参数,但它也影响Hive的性能。此参数控制Reduce任务的数量。合理设置此值可以平衡负载并减少执行时间。

SET mapreduce.job.reduces = 10;

6.hive.optimize.sort.dynamic.partition

当设置为true时,此参数会对动态分区操作进行排序,以减少作为Reduce阶段一部分的I/O操作。这对于提高包含大量动态分区的查询的性能非常有用。

SET hive.optimize.sort.dynamic.partition = true;

实践建议

        在调整这些参数时,重要的是要记住,并没有一套适合所有情况的最佳设置。最佳的参数设置取决于具体的查询类型、数据量、集群大小和其他因素。因此,进行参数调优时应该采取迭代的方法,逐一调整参数,观察性能变化,从而找到最适合你当前工作负载的配置。

技巧总结

        各种优化技巧和相应代码示例。这些优化措施包括但不限于并行处理、动态分区、向量化查询执行以及MapReduce作业的调整。

-- 启用并行执行以提高任务处理速度
SET hive.exec.parallel = true;
SET hive.exec.parallel.thread.number = 8; -- 根据你的集群资源调整线程数

-- 启用动态分区以便在执行插入操作时自动创建分区
SET hive.exec.dynamic.partition = true;
SET hive.exec.dynamic.partition.mode = nonstrict;

-- 启用向量化查询执行,以利用CPU的向量化指令来加速处理
SET hive.vectorized.execution.enabled = true;
SET hive.vectorized.execution.reduce.enabled = true;

-- 调整Reduce任务的数量以平衡负载并减少执行时间
SET mapreduce.job.reduces = 10; -- 根据数据量和查询复杂度来调整

-- 对动态分区操作进行排序,以减少Reduce阶段的I/O操作
SET hive.optimize.sort.dynamic.partition = true;

-- 示例:创建分区表并使用优化的查询
CREATE TABLE employees_partitioned (
  id INT,
  name STRING,
  age INT
)
PARTITIONED BY (department STRING)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY ','
STORED AS TEXTFILE;

-- 加载数据进入分区表
LOAD DATA LOCAL INPATH '/path/to/employees.txt' INTO TABLE employees_partitioned PARTITION(department);

-- 针对特定分区执行查询,减少扫描数据量
SELECT * FROM employees_partitioned WHERE department = 'Sales';

        一些查询优化的实用示例,比如使用合适的JOIN类型、合理利用WHERE子句来过滤数据,以及使用合适的数据存储格式和分区策略来提高查询效率

-- 启用向量化查询执行
SET hive.vectorized.execution.enabled = true;
SET hive.vectorized.execution.reduce.enabled = true;

-- 限制查询结果,仅用于测试和开发阶段
SELECT name, age FROM employees WHERE age > 30 LIMIT 100;

-- 使用INNER JOIN代替CROSS JOIN,并在JOIN之前过滤数据
SELECT e.name, d.department_name
FROM employees e
JOIN departments d ON e.department_id = d.id
WHERE e.age > 25 AND d.location = 'New York';

-- 使用MAPJOIN优化小表JOIN大表
SELECT /*+ MAPJOIN(small_table) */ big_table.*
FROM big_table
JOIN small_table ON big_table.key = small_table.key;

-- 使用窗口函数进行优化的聚合查询
SELECT department, AVG(salary) OVER (PARTITION BY department) as avg_salary
FROM employees;

-- 使用SORT BY进行局部排序,避免全局排序的开销
SELECT * FROM employees ORDER BY name SORT BY age;

-- 使用分区键进行查询,减少扫描的数据量
SELECT * FROM employees_partitioned WHERE department = 'Sales';

-- 使用DISTRIBUTE BY和SORT BY组合优化GROUP BY操作
SELECT department, COUNT(*) FROM employees
DISTRIBUTE BY department
SORT BY department
GROUP BY department;

-- 使用EXPLAIN命令检查执行计划
EXPLAIN
SELECT name, age FROM employees WHERE age > 30;

-- 使用COLLECT_SET来去重聚合
SELECT department, COLLECT_SET(name)
FROM employees
GROUP BY department;

-- 避免使用NOT IN和NOT EXISTS,使用LEFT SEMI JOIN代替
SELECT e.name
FROM employees e
LEFT SEMI JOIN departments d ON e.department_id = d.id
WHERE d.department_name = 'Sales';

-- 注意:每一种优化策略都需要根据具体的查询和数据环境进行调整和测试以验证其有效性。

具体的HiveQL代码示例

-- 1. 使用内连接代替全连接,减少数据量
SELECT a.*, b.*
FROM table_a a
JOIN table_b b ON a.key = b.key;

-- 2. 在JOIN前使用WHERE子句过滤,减少JOIN操作的数据量
SELECT a.*, b.*
FROM table_a a
JOIN table_b b ON a.key = b.key
WHERE a.date = '2024-03-17';

-- 3. 利用MAPJOIN优化小表与大表的JOIN操作
SELECT /*+ MAPJOIN(small_table) */ big_table.*, small_table.*
FROM big_table
JOIN small_table ON big_table.key = small_table.key;

-- 4. 仅选择需要的列,避免使用SELECT *
SELECT id, name, department
FROM employees;

-- 5. 使用分区查询,减少扫描的数据量
SELECT *
FROM sales_data
WHERE partition_date = '2024-03-17';

-- 6. 使用SORT BY代替ORDER BY进行局部排序
SELECT name, age
FROM employees
SORT BY age;

-- 7. 使用CLUSTER BY在分布式处理时同时进行数据分配和排序
SELECT name, department
FROM employees
CLUSTER BY department;

-- 8. 使用LIMIT进行测试,限制结果集大小
SELECT *
FROM large_table
LIMIT 100;

-- 9. 使用EXPLAIN命令分析查询执行计划
EXPLAIN
SELECT name, sum(salary)
FROM employees
GROUP BY name;

-- 10. 开启向量化查询执行
SET hive.vectorized.execution.enabled = true;
SET hive.vectorized.execution.reduce.enabled = true;

-- 11. 压缩MapReduce作业的中间结果
SET hive.exec.compress.intermediate = true;

-- 12. 使用窗口函数优化聚合操作
SELECT name,
       department,
       AVG(salary) OVER (PARTITION BY department) as avg_dept_salary
FROM employees;

-- 13. 使用COLLECT_SET聚合函数去重
SELECT department, COLLECT_SET(name)
FROM employees
GROUP BY department;

-- 14. 使用DISTRIBUTE BY和SORT BY优化GROUP BY操作,减少数据倾斜
SELECT department, count(*)
FROM employees
DISTRIBUTE BY department
SORT BY department;

-- 15. 使用SEMI JOIN减少数据传输
SELECT a.*
FROM table_a a
WHERE EXISTS (SELECT 1 FROM table_b b WHERE a.key = b.key);

-- 16. 避免复杂正则表达式,简化查询条件
SELECT *
FROM logs
WHERE url LIKE '%openai%';

-- 17. 优化CASE语句,将最可能的情况放在前面
SELECT name,
       CASE WHEN age < 20 THEN 'Generation Z'
            WHEN age BETWEEN 20 AND 39 THEN 'Millennials'
            ELSE 'Other'
       END as generation
FROM employees;

-- 18. 使用动态分区插入,优化数据写入操作
SET hive.exec.dynamic.partition = true;
SET hive.exec.dynamic.partition.mode = nonstrict;
INSERT INTO TABLE employees_partitioned PARTITION(department)
SELECT id, name, age, department
FROM employees_staging;

-- 19. 使用TEZ引擎优化执行
SET hive.execution.engine=tez;

-- 20. 优化GROUP BY操作,使用GROUP BY ... SKEWED BY
SET hive.groupby.skewindata=true;
SELECT department, count(*)
FROM employees
GROUP BY department;

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

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

相关文章

考研数二要掌握的高中知识点(四)

文章目录 一、正切函数的图像性质二、三角函数恒等变换公式1. 同角齐次式2. 两角和与差公式3. 辅助角公式4. 二倍角公式5. 降幂公式6. 半角公式&#xff08;二倍角公式的变形&#xff09;7. 万能公式 三、反三角函数1. 反正弦函数2. 反余弦函数3. 反正切函数 一、正切函数的图像…

保研|资讯|夏令营|3.31截止!香港城市大学市场营销学系首届学术暑期夏令营

香港城市大学市场营销学系首届学术暑期夏令营 1 项目简介 我们的博士项目致力为未来营销科学和工商管理学界培养一流学者和行业领袖。博士项目一般为期四到六年&#xff0c;允许本科生直接申请。课程包括实证分析模型&#xff0c;消费者行为研究&#xff0c;博弈微观模型&…

自定义方法SQL注入器-DefaultSqlInjector

/*** 自定义Sql注入* author zy*/ public class SqlInjector extends DefaultSqlInjector {Overridepublic List<AbstractMethod> getMethodList(Class<?> mapperClass, TableInfo tableInfo) {// 注意&#xff1a;此SQL注入器继承了DefaultSqlInjector(默认注入器…

【prometheus】k8s集群部署prometheus server(文末送书)

目录 一、概述 1.1 prometheus简介 1.2 prometheus架构图 1.3测试环境 二、k8s集群中部署prometheus server 2.1创建sa账号和数据目录 2.2安装prometheus 2.2.1创建configmap存储卷存放prometheus配置信息 2.2.2 通过deployment部署prometheus 2.2.3prometheus pod创…

HBase在表操作--显示中文

启动HBase后&#xff0c;Master和RegionServer两个服务器&#xff0c;分别对应进程为HMaster和HRegionServe。&#xff08;可通过jps查看&#xff09; 1.进入表操作 hbase shell 2.查看当前库中存在的表 list 3.查看表中数据&#xff08;注&#xff1a;学习期间可用&#…

Python小白笔记

输入 # 一行输入多个数字&#xff0c;空格隔开&#xff0c;存入列表a中 a list(map(int, input().split())) print(a) >>>21 22 34 54 67 >>>[21, 22, 34, 54, 67] 输出 数据&#xff1a; print(%d%10.3f%(x,y)) y的精度为3&#xff0c;宽度为10 %0 …

【Java】十大排序

目录 冒泡排序 选择排序 插入排序 希尔排序 归并排序 快速排序 堆排序 计数排序 桶排序 基数排序 冒泡排序 冒泡排序(Bubble Sort)是一种简单的排序算法。它重复地遍历要排序的序列&#xff0c;依次比较两个元素&#xff0c;如果它们的顺序错误就把它们交换过来。遍历…

oracle 19c打补丁到19.14

oracle 19c打补丁到19.14 oracle 19.3打补丁到19.14 查看oracle的版本&#xff1a; SQL> column product format A30 SQL> column version format A15 SQL> column version_full format A20 SQL> column status format A15 SQL> select * from product_compo…

【对顶队列】【中位数贪心】【前缀和】100227. 拾起 K 个 1 需要的最少行动次数

本文涉及知识点 C算法&#xff1a;前缀和、前缀乘积、前缀异或的原理、源码及测试用例 包括课程视频 对顶队列&#xff08;栈&#xff09; 分类讨论 LeetCode100227. 拾起 K 个 1 需要的最少行动次数 给你一个下标从 0 开始的二进制数组 nums&#xff0c;其长度为 n &#x…

【LabVIEW FPGA入门】浮点数类型支持

如今&#xff0c;使用浮点运算来设计嵌入式系统的需求变得越来越普遍。随着 FPGA 因其固有的大规模并行性而在浮点性能方面继续超越微处理器&#xff0c;这种情况正在加剧。线性代数和数字信号处理 (DSP) 等高级算法可以受益于浮点数据类型的高动态范围精度。LabVIEW FPGA 通过…

Vue项目的搭建

Node.js 下载 Node.js — Download (nodejs.org)https://nodejs.org/en/download/ 安装 测试 winR->cmd执行 node -v配置 在安装目录下创建两个子文件夹node_cache和node_global,我的就是 D:\nodejs\node_cache D:\nodejs\node_global 在node_global文件下再创建一个…

视频基础知识(一) 视频编码 | H.26X 系列 | MPEG 系列 | H.265

文章目录 一、视频编码二、 H.26X 系列1、H.2612、H.2633、H.2643.1 I帧3.2 P帧3.3 B帧 4、H.265 三、 MPEG 系列1、MPEG-12、MPEG-23、MPEG-44、MPEG-7 &#x1f680; 个人简介&#xff1a;CSDN「博客新星」TOP 10 &#xff0c; C/C 领域新星创作者&#x1f49f; 作 者&…

【HTML】HTML表单8.2(表单标签2)

目录 接上期&#xff0c;大致实现效果 文章简要 注释&#xff1a;这一次介绍的很多效果需要后期与服务器配合&#xff0c;但我们这里先只介绍效果 ①提交按钮 ②获取验证码 ③上传文件 ④还原所有表单内容 ⑤下拉表单 ⑥文字域 接上期&#xff0c;大致实现效果 文章简要 注…

OpenCV-Java 开发简介

返回目录&#xff1a;OpenCV系列文章目录&#xff08;持续更新中......&#xff09; 上一篇&#xff1a;如何在“Microsoft Visual Studio”中使用OpenCV编译应用程序 下一篇&#xff1a;如何将OpenCV Java 与Eclipse结合使用 警告&#xff1a; 本教程可能包含过时的信息。 …

伺服电机编码器的分辨率指得是什么?

伺服电机编码器的分辨率是伺服电机编码器的重要参数。 一般来说&#xff0c;具体的伺服电机编码器型号可以找到对应的分辨率值。 伺服电机编码器的分辨率和精度不同&#xff0c;但也有一定的关系。 伺服电机编码器的分辨率是多少&#xff1f; 1、伺服编码器&#xff08;同步伺…

【JS】html字符转义

需求 将html转为字符串将html字符串转义&#xff0c;比如<div>转为<div> 码 /*** html标签字符转义* param {Stirng} str 要转换的html字符* returns String 返回转义的html字符串*/ const elToStr str > str.replaceAll(<, <).replaceAll(>, >)…

Github: Github actions自动化工作原理与多workflow创建和部署

Github actions 1 &#xff09;概述 Github Actions 是Github官方推出的 CI/CD 解决方案 https://docs.githu.com/en/actions 优点 自动发布流程可减少发布过程中手动操作成本&#xff0c;大幅提升ci/cd效率&#xff0c;快速实现项目发布上线 缺点 存在较高的技术门槛需要利用…

论文阅读:Face Deblurring using Dual Camera Fusion on Mobile Phones

今天介绍一篇发表在 ACM SIGGRAPH 上的文章&#xff0c;是用手机的双摄系统来做人脸去模糊的工作。这也是谷歌计算摄影研究组的工作。 快速运动物体的运动模糊在摄影中是一个一直以来的难题&#xff0c;在手机摄影中也是非常常见的问题&#xff0c;尤其在光照不足&#xff0c;…

【FPGA/IC】什么是模块化设计?

什么是模块化设计 FPGA/IC设计中根据模块层次的不同有两种基本的设计方法&#xff1a; 自下而上方法对设计进行逐次划分的过程是从基本单元出发的&#xff0c;设计树最末枝上的单元是已经设计好的基本单元&#xff0c;或者其他项目开发好的单元或者IP。该方法先对底层的功能块…

8-图像缩放

其实&#xff0c;就是开辟一个zoomwidth&#xff0c;zoomheight的内存&#xff0c;再分别赋值即可。 void CDib::Scale(float xZoom, float yZoom) { //指向原图像指针 LPBYTE p_data GetData(); //指向原像素的指针 LPBYTE lpSrc; //指向缩放图像对应像素的指针 LPBYTE lpDs…