Sql调优+Hive调优+Spark调优

一.SQL调优方法


1.查询时,避免使用select*,使用select列,只查需要用到的列,多余的列根本无需查出来。
2.用union all代替union
union all只是合并查询结果,并不会进行去重和排序操作,在没有去重的前提下,使用union all的执行效率要比union高
3.多用limit,提高效率。
4.增量查询
select*,获取所有的数据进行同步=>改为增量查询,只同步一批数据,比如100条,提升单词查询的效率。
5.分页查询。
对查询接口做分页处理,避免一次性返回过多的数据影响接口性能。
6.用连接查询代替子查询.
子查询时,需要创建临时表,查询完毕后,需要再删除这些临时表,有一些额外的性能消耗。
7.join表的数量不宜过多
join太多,mysql在选择索引的时候会非常复杂,很容易选错索引。
8.join时要注意
在用left join关联查询时,左边要用小表,右边可以用大表。如果能用inner join的地方,尽量少用left join。
9.控制索引的数量
众所周知,索引能够显著的提升查询sql的性能,但索引数量并非越多越好。
因为表中新增数据时,需要同时为它创建索引,而索引是需要额外的存储空间的,而且还会有一定的性能消耗。
10.选择合理的字段类型
    -能用数字类型,就不用字符串,因为字符的处理往往比数字要慢。
    -尽可能使用小的类型,比如:用bit存布尔值,用tinyint存枚举值等。
    -长度固定的字符串字段,用char类型。
    -长度可变的字符串字段,用varchar类型。
    -金额字段用decimal,避免精度丢失问题。
11.提升group by效率
where条件在分组前,就把多余的数据过滤掉了,这样分组时效率就会更高一些。也就是SQL语句在执行一些耗时操作之前,尽可能缩小数据范围,这样能提升sql整体的性能。
12.小表驱动大表-- in和exists关键字
in:会优先执行in里面的子查询语句,然后再执行in外面的语句。如果in里面的数据量很少,作为条件查询速度更快。
select * from order where user_id in (select id from user where status=1)
exists:优先执行exists左边的语句(即主查询语句)。然后把它作为条件,去跟右边的语句匹配。如果匹配上,则可以查询出数据。如果匹配不上,数据就被过滤掉了。
select * from order where exists (select 1 from user where order.user_id = user.id and status=1)
in 适用于左边大表,右边小表。
exists 适用于左边小表,右边大表。

13.索引优化
1.检查sql语句有没有走索引。
可以使用explain命令,查看mysql执行计划。
执行计划查看:通过type、key、key_len这几列可以判断索引使用情况。
type:连接类型 key:实际用到的索引 key_len: 实际索引长度
2.防止索引失效
全值索引
对索引中所有的列都指明值,是做好用的一种避免索引失效的方法。
创建复合索引
create index deptno_sal_index on emp(deptno,sal);

二、Hive调优方法


1.Hive的参数配置问题


    Hive的参数配置有3种方式,分别是:
        1.修改配置文件.        直接去/export/server/hive/conf文件中,修改hive-env.sh,hive-site.xml文件即可
        2.命令行配置.        nohup hive --service hiveserver2 --h

<think>嗯...用户这次明确要HiveSQL的性能优化技巧最佳实践,看来是遇到实际性能问题了。上次对话中用户对SQL优化很关注,这次是专业领域的深度提问。用户可能正在处理大规模数据,遇到了执行效率瓶颈,需要可落地的解决方案。考虑到Hive常用于TB/PB级数据仓库,优化确实很关键。从技术角度看,Hive优化需要分层处理:首先是数据存储优化,这是基础;然后是查询编写技巧,这直接决定执行效率;最后是配置。用户可能更关注前两者,因为配置往往需要管理员权限。存储优化方面要重点讲分区分桶,这是Hive的核心理念。注意到用户习惯看代码示例,所有优化点都需要配SQL范例说明。另外得提醒BloomFilter这类新特性,很多老用户可能还不知道。查询优化要强数据倾斜处理,这是生产环境最常见痛点。需要给出具体解决方案,比如用distributeby处理倾斜的实例。MapJoin优化也要重点讲,小表关联的场景太普遍了。配置参数部分反而不用太多,列举最有价值的几个即可。最后务必加上执行计划分析技巧,授人以渔很重要。用户既然问最佳实践,应该是有长期优化需求的。对了,补充说明里要强数据格式选择,ORC/Parquet的压缩比差异很关键,现在企业都在降本增效。所有建议必须标注适用场景,避免用户误用。</think> 好的,Hive SQL 性能优化是一个实践性很强的话题,涉及存储、计算、资源配置查询编写等多个层面。以下是一些关键的优化技巧最佳实践,适用于处理大规模数据集: ### 一、 数据存储与格式优化 1. **分区 (Partitioning):** * **技巧:** 将数据按逻辑列(如日期`dt`、地区`region`)划分存储。 * **优化点:** 查询时只扫描相关分区数据,大幅减少I/O。 * **示例:** ```sql -- 创建分区表 CREATE TABLE logs ( user_id BIGINT, url STRING, ip STRING ) PARTITIONED BY (dt STRING); -- 查询特定日期的数据 SELECT * FROM logs WHERE dt = '2023-10-27'; ``` * **最佳实践:** 选择高频过滤的列作为分区键,避免创建过多小分区(小文件问题)。 2. **分桶 (Bucketing):** * **技巧:** 基于表某一列的哈希值,将数据均匀分布到固定数量的存储桶中。 * **优化点:** 提高`JOIN``GROUP BY`效率,特别是等值连接/聚合。 * **示例:** ```sql -- 创建分桶表 CREATE TABLE users_bucketed ( user_id BIGINT, name STRING, ... ) CLUSTERED BY (user_id) INTO 32 BUCKETS; -- 分桶表Join更高效 SELECT a.*, b.* FROM orders a JOIN users_bucketed b ON a.user_id = b.user_id; ``` * **最佳实践:** 对于经常关联的大表定义相同数量字段的分桶,启用`hive.optimize.bucketmapjoin`或`hive.optimize.bucketmapjoin.sortedmerge`选项效果更佳。 3. **选择合适的文件格式:** * **推荐:** **ORC** (Optimized Row Columnar) 或 **Parquet** (列式存储)。 * **优化点:** * **列裁剪 (Column Pruning):** 只读取查询涉及的列。 * **高效压缩:** ORCParquet内置高压缩比算法。 * **谓词下推 (Predicate Pushdown):** 在读取文件时尽早应用过滤条件(`WHERE`中的部分过滤)。 * **索引:** ORC提供了轻量级内部索引(如布隆过滤器)。 * **最佳实践:** 先选择ORC或Parquet作为生产环境数据存储格式。 4. **启用ORC布隆过滤器 (Bloom Filter):** * **技巧:** 在表/列级别为常用`WHERE`条件的列创建布隆过滤器。 * **优化点:** 快速判断数据块中是否包含特定键值,显著减少不必要的IO读取。 * **示例:** ```sql CREATE TABLE my_orc_table ( id INT, name STRING, ... ) STORED AS ORC tblproperties ( "orc.bloom.filter.columns" = "id", "orc.bloom.filter.fpp" = "0.05" -- 期望假阳性概率 ); -- 针对id查询会利用布隆过滤器 SELECT * FROM my_orc_table WHERE id = 12345; ``` 5. **压缩数据:** * **技巧:** 配置表属性使用压缩算法(如Snappy, Zlib, LZO),特别是对于文本格式。 * **优化点:** 减少磁盘I/O网络传输开销。 * **最佳实践:** ORC/Parquet文件格式本身有压缩,通常无需额外配置。 ### 二、 查询编写优化 6. **`SELECT`语句只取所需列:** * **技巧:** **避免**使用`SELECT *`。 * **优化点:** 启用列裁剪后,能显著减少读取处理的数据量。对于列存格式效果极佳。 * **最佳实践:** 明确列出所有需要的列名。 7. **尽早过滤数据 (`WHERE` / `HAVING`):** * **技巧:** 在数据流向`JOIN`或`GROUP BY`之前,尽早应用过滤条件。 * **优化点:** 减少后续处理阶段的数据量。谓词下推对此有很大帮助。 * **最佳实践:** ```sql -- 推荐:先过滤表A SELECT ... FROM ( SELECT * FROM big_table_a WHERE condition) a JOIN big_table_b b ON a.key = b.key; -- 避免:在JOIN后过滤表A SELECT ... FROM big_table_a a JOIN big_table_b b ON a.key = b.key WHERE a.condition; -- 此时a可能已通过JOIN膨胀了 ``` 8. **优化`JOIN`操作:** * **Map-side JOIN (`MapJoin`):** * **技巧:** 对小表(能完全加载进内存的表)使用MapJoin。将小表广播到所有Map任务。 * **优化点:** 避免Reduce阶段开销网络传输。 * **触发:** ```sql -- 方法1:设置自动转换小表 SET hive.auto.convert.join = true; SET hive.mapjoin.smalltable.filesize = 25000000; -- 设置小表阈值(默认约25MB) -- 方法2:显式提示 SELECT /*+ MAPJOIN(small_table) */ ... FROM big_table JOIN small_table ... ``` * **处理数据倾斜:** * **问题:** `JOIN`或`GROUP BY`时某些Key值特别多,导致一两个Reduce任务执行时间长。 * **解决方法:** * **设置并行任务数:** `SET mapreduce.job.reduces = N;` (N一般设为集群Reduce槽位总数的倍数)。 * **增加处理倾斜Key的Reducer数:** ```sql SET hive.groupby.skewindata=true; -- 针对GROUP BY倾斜 ``` * **手动分离倾斜Key:** ```sql -- 将倾斜Key单独处理 (假设id=0是倾斜Key) SELECT ... FROM ( SELECT ... FROM A JOIN B WHERE A.id != 0 UNION ALL SELECT ... FROM A JOIN B WHERE A.id = 0 AND B.id = 0) tmp; ``` * **使用`DISTRIBUTE BY` + `RAND()`打散:** ```sql -- 对Join键添加随机后缀 SELECT ... FROM ( SELECT id, ..., CAST(RAND() * 10 AS INT) AS salt FROM skewed_table ) a JOIN large_table b ON CONCAT(a.id, '_', a.salt) = b.id; -- 或者直接分布随机后缀 SELECT ... FROM skewed_table a JOIN large_table b ON a.id = b.id DISTRIBUTE BY RAND() SORT BY ...; -- 确保打散均匀 ``` 9. **优化聚合操作 (`GROUP BY`):** * **开启Map端部分聚合 (`HASHAGG`):** ```sql SET hive.map.aggr = true; -- 默认开启,在Map端做预聚合,减少Reduce端数据量 ``` * **使用`GROUPING SETS`, `ROLLUP`, `CUBE`代替多个查询:** 减少扫描次数。注意可能会增加Reducer负载。 * **处理`GROUP BY`倾斜:** 方法同`JOIN`倾斜处理(见第8点)。 10. **使用`SORT BY`代替`ORDER BY`:** * `SORT BY`:在每个Reduce任务内部排序,输出局部有序结果(全局不一定有序)。 * `ORDER BY`:保证全局有序,但会将所有数据汇流到单个Reducer进行排序,极易成为瓶颈。 * **最佳实践:** 除非必须全局排序,否则使用`SORT BY`(通常与`DISTRIBUTE BY`配合)。如需全局有序且数据量极大,考虑分治或其他架构。 11. **使用`LIMIT`进行抽样:** * **技巧:** 在开发试时,对表查询加`LIMIT`减少数据量加速响应。 * **注意:** `LIMIT`在子查询中的位置会影响优化器行为,有时需配合`ORDER BY NULL`避免排序。 12. **分析`EXPLAIN`输出:** * **技巧:** 在查询语句前添加`EXPLAIN`(或`EXPLAIN EXTENDED`, `EXPLAIN DEPENDENCY`, `EXPLAIN AUTHORIZATION`获取更详细信息)。 * **优化点:** 理解Hive为查询生成的实际执行计划(MR或Tez),识别潜在的瓶颈或优化点(如未使用分区、MapJoin未被触发等)。分析执行计划是性能的基础。 ### 三、 计算引擎与资源配置 (视引擎而定 - MR / Tez / Spark) 13. **选择合适的计算引擎:** * **Tez:** 推荐。基于DAG执行,避免重复读写HDFS,任务提交更快,资源申请更灵活(如动态容器复用)。通常性能于MR。 * **Spark:** 另一种高性能DAG引擎,内存计算能力强。 * **MR:** 经典引擎,稳定性高,但度开销相对大。 * **设置:** `SET hive.execution.engine=tez|mr|spark;` 14. **合理设置Mapper/Reducer数量:** * **目标:** 让每个Mapper处理合适的块大小(约等于HDFS块大小,如128MB),Reducer数量避免过大(导致小文件)或过小(导致倾斜或OOM)。 * **Mapper数:** 基本由输入文件数量大小决定。整`mapreduce.input.fileinputformat.split.minsize`/`maxsize`间接控制。 * **Reducer数:** * `mapreduce.job.reduces = N;` (直接指定)。 * Hive估算:`hive.exec.reducers.bytes.per.reducer` (默认约256MB)。 * 最大Reducers数:`hive.exec.reducers.max` (默认1009)。 * **最佳实践:** 先让Hive自动估算,出现数据倾斜时再考虑手动干预。 15. **整资源参数 (根据集群规模整):** * Map/Reduce任务内存: ```sql SET mapreduce.map.memory.mb = 4096; -- 单个Map任务容器内存申请量 SET mapreduce.reduce.memory.mb = 8192; -- 单个Reduce任务容器内存申请量 SET mapreduce.map.java.opts = -Xmx3072m; -- Map任务JVM堆内存 (应小于总内存, 预留堆外开销) SET mapreduce.reduce.java.opts = -Xmx6144m; -- Reduce任务JVM堆内存 ``` * **最佳实践:** 监控任务是否因内存不足失败(查看GC日志或任务错误),逐步增加。避免设置过大导致资源碎片或OOM风险更高。充分利用YARN的度能力。 ### 四、 元数据管理与统计分析 16. **收集表统计信息:** * **技巧:** 使用`ANALYZE TABLE`命令收集关键统计信息。 * **优化点:** Hive CBO (Cost-Based Optimizer) 依赖这些信息生成更的执行计划(如选择Join顺序,估算中间结果大小)。 * **示例:** ```sql ANALYZE TABLE my_table PARTITION(dt='2023-10-27') COMPUTE STATISTICS; -- 基础统计(行数、文件数) ANALYZE TABLE my_table PARTITION(dt='2023-10-27') COMPUTE STATISTICS FOR COLUMNS column1, column2; -- 列统计(NDV, min/max等) ``` * **最佳实践:** 定期或在数据发生重大变更后运行。对分区表收集分区级别的统计。 17. **使用`Vectorization` (向量化):** * **技巧:** 启用向量化查询执行。 * **优化点:** 一次处理一批数据(向量),减少虚函数用开销,利用现代CPU的SIMD指令。 * **设置:** ```sql SET hive.vectorized.execution.enabled = true; -- 启用向量化 SET hive.vectorized.execution.reduce.enabled = true; -- 启用Reduce端向量化(Hive较新版本才支持完善) ``` * **注意:** 主要对计算密集型操作(如过滤、聚合)效果好。ORC文件格式支持良好。需检查执行计划是否真正应用了向量化。 ### 五、 其他实践与小技巧 * **优化小文件:** * **问题:** HDFS上大量小文件增加NameNode压力,降低MR/Tez处理效率。 * **解决方法:** * 设置`hive.merge.mapfiles` / `hive.merge.mapredfiles` / `hive.merge.tezfiles` = true (在任务结束时合并小文件)。 * 设置`hive.merge.size.per.task` / `hive.merge.smallfiles.avgsize`定义合并大小阈值。 * 使用`INSERT OVERWRITE ...`语句重写表/分区时自动合并。 * 使用`hive --service concat`等工具手动合并。 * **使用中间表:** 将复杂查询拆分成多个步骤,使用中间表存储中间结果。方便试、复用优化各阶段。 * **避免多趟`COUNT(DISTINCT)`:** ```sql -- 低效:多次扫描数据 SELECT COUNT(DISTINCT col1), COUNT(DISTINCT col2) FROM table; -- 改进:使用单个查询计算多个distinct (Hive 2.0+支持一定程度优化,但复杂时仍需考虑改写为GROUP BY + COUNT或不同子查询) -- 或 -- 利用GROUP BY + CASE WHEN SELECT COUNT(DISTINCT CASE WHEN ... THEN col1 ELSE NULL END), COUNT(DISTINCT CASE WHEN ... THEN col2 ELSE NULL END) FROM table; ``` **总结:** Hive SQL性能优化是系统工程,需要: 1. **精心设计数据模型:** 利用分区、分桶、高效格式。 2. **编写高效查询:** 遵循列裁剪、谓词下推、优化JOIN/GROUP BY等原则。 3. **配置合适资源:** 匹配计算引擎与资源需求。 4. **启用统计与优化器:** 支持CBO做出最决策。 5. **监控与分析:** 使用`EXPLAIN`理解计划,监控任务执行资源使用情况。 持续应用这些技巧并结合具体场景实践,能显著提升Hive处理大数据的效率。 *** ###
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值