性能优化与最佳实践

第十九章 性能优化与最佳实践

19.1 性能优化概述

19.1.1 性能瓶颈来源

来源 表现 优化方向
数据量 大文件加载慢 数据简化、索引
渲染 地图绘制卡顿 简化符号、缓存
内存 程序崩溃 优化数据结构
IO 读写慢 SSD、缓存
网络 Web服务响应慢 缓存、代理

19.2 数据优化

19.2.1 空间索引

创建空间索引

# Shapefile
processing.run("native:createspatialindex", {'INPUT': layer})

# PostGIS
# CREATE INDEX idx_geom ON table USING GIST(geom);

# SpatiaLite
# SELECT CreateSpatialIndex('table', 'geometry');

19.2.2 几何简化

# 简化几何
result = processing.run("native:simplifygeometries", {
    'INPUT': layer,
    'METHOD': 0,  # Douglas-Peucker
    'TOLERANCE': 10,
    'OUTPUT': 'memory:'
})

19.2.3 数据分块

# 按网格分割大数据集
result = processing.run("native:creategrid", {
    'TYPE': 2,  # Rectangle
    'EXTENT': layer.extent(),
    'HSPACING': 10000,
    'VSPACING': 10000,
    'OUTPUT': 'memory:'
})

# 按网格裁剪
for grid_feature in grid_layer.getFeatures():
    result = processing.run("native:clip", {
        'INPUT': layer,
        'OVERLAY': grid_feature.geometry(),
        'OUTPUT': f'/output/tile_{grid_feature.id()}.gpkg'
    })

19.2.4 使用高效格式

推荐格式

  • GeoPackage(比Shapefile高效)
  • FlatGeobuf(流式处理)
  • Cloud Optimized GeoTIFF(栅格)
  • 空间数据库(大量数据)
# 转换为GeoPackage
processing.run("native:package", {
    'LAYERS': [layer1, layer2],
    'OUTPUT': '/output/data.gpkg',
    'OVERWRITE': True
})

19.3 渲染优化

19.3.1 简化比例尺

设置 > 选项 > 渲染
简化阈值: 1.0
按比例简化

19.3.2 图层比例尺依赖

# 设置图层可见比例尺
layer.setMinimumScale(1000000)  # 最小比例尺
layer.setMaximumScale(1000)     # 最大比例尺
layer.setScaleBasedVisibility(True)

19.3.3 使用缓存

设置 > 选项 > 渲染
渲染缓存: 启用

19.3.4 金字塔/概览图

栅格金字塔

图层属性 > 金字塔 > 构建金字塔

矢量简化图层
为不同比例尺准备不同详细程度的图层。

19.3.5 符号优化

避免复杂符号

  • 减少符号图层数
  • 避免复杂图案填充
  • 使用简单形状
# 简单符号比复杂符号渲染快
simple = QgsMarkerSymbol.createSimple({'name': 'circle', 'size': '3'})
# 比多层叠加符号快很多

19.4 内存管理

19.4.1 及时释放资源

# 删除不需要的图层
QgsProject.instance().removeMapLayer(layer.id())

# 显式清理
del layer

# 强制垃圾回收
import gc
gc.collect()

19.4.2 使用迭代器

# 好的做法:使用迭代器
for feature in layer.getFeatures():
    # 处理feature
    pass

# 避免:一次性加载所有要素到列表
# features = list(layer.getFeatures())  # 大数据集会消耗大量内存

19.4.3 限制请求

# 只获取需要的字段
request = QgsFeatureRequest()
request.setSubsetOfAttributes(['id', 'name'], layer.fields())

# 限制几何
request.setFlags(QgsFeatureRequest.NoGeometry)

# 限制数量
request.setLimit(1000)

# 空间过滤
request.setFilterRect(extent)

19.4.4 分批处理

# 分批处理大数据
batch_size = 1000
features = layer.getFeatures()

batch = []
for feature in features:
    batch.append(feature)
    
    if len(batch) >= batch_size:
        process_batch(batch)
        batch = []

# 处理剩余
if batch:
    process_batch(batch)

19.5 Processing优化

19.5.1 使用临时输出

# 使用内存输出(小数据)
result = processing.run("native:buffer", {
    'INPUT': layer,
    'OUTPUT': 'memory:'
})

# 使用临时文件(大数据)
result = processing.run("native:buffer", {
    'INPUT': layer,
    'OUTPUT': QgsProcessingContext().tempFilePath('.gpkg')
})

19.5.2 禁用不需要的输出

# 只获取需要的输出
result = processing.run("native:buffer", {
    'INPUT': layer,
    'OUTPUT': 'memory:'
})
# 只使用result['OUTPUT']

19.5.3 并行执行

from concurrent.futures import ProcessPoolExecutor

def run_analysis(params):
    return processing.run("native:buffer", params)

# 并行执行多个分析
with ProcessPoolExecutor(max_workers=4) as executor:
    results = list(executor.map(run_analysis, param_list))

19.6 数据库优化

19.6.1 查询优化

-- 使用空间索引
SELECT * FROM table
WHERE ST_Intersects(geom, ST_MakeEnvelope(100, 30, 120, 45, 4326))

-- 避免全表扫描
-- 使用 LIMIT
-- 只选择需要的列
SELECT id, name FROM table LIMIT 1000

19.6.2 连接池

# QGIS自动管理数据库连接
# 对于自定义应用,使用连接池
from sqlalchemy import create_engine
from sqlalchemy.pool import QueuePool

engine = create_engine(
    'postgresql://user:pass@host/db',
    poolclass=QueuePool,
    pool_size=5,
    max_overflow=10
)

19.6.3 服务端处理

-- 在数据库端完成计算
SELECT 
    region_name,
    COUNT(*) as point_count,
    SUM(population) as total_pop
FROM points p
JOIN regions r ON ST_Within(p.geom, r.geom)
GROUP BY region_name

19.7 网络优化

19.7.1 启用缓存

设置 > 选项 > 网络 > 缓存
目录: /path/to/cache
大小: 500 MB

19.7.2 代理设置

设置 > 选项 > 网络 > 代理
启用代理加速访问

19.7.3 本地瓦片缓存

# 使用本地瓦片缓存
# 配置XYZ瓦片源时使用本地缓存服务

19.8 项目优化

19.8.1 项目设置

项目 > 属性 > 通用
- 评估默认值: 仅在需要时
- 自动事务分组: 按需启用

19.8.2 减少图层数量

  • 合并相似图层
  • 使用规则渲染代替多图层
  • 移除不需要的图层

19.8.3 优化启动

设置 > 选项 > 通用
- 检查QGIS版本: 禁用
- 加载插件: 只加载必要的

19.9 最佳实践

19.9.1 数据管理

实践 说明
使用GeoPackage 比Shapefile更高效
创建空间索引 加速空间查询
数据分层 按比例尺使用不同详细程度
定期清理 删除临时文件和缓存

19.9.2 项目管理

实践 说明
相对路径 便于项目迁移
模板使用 标准化项目设置
版本控制 跟踪项目变更
文档记录 记录数据源和处理步骤

19.9.3 代码实践

# 使用上下文管理器
with edit(layer):
    layer.addFeature(feature)

# 批量操作
layer.startEditing()
layer.dataProvider().addFeatures(features)
layer.commitChanges()

# 错误处理
try:
    result = processing.run(...)
except QgsProcessingException as e:
    print(f"处理错误: {e}")

19.9.4 工作流程

  1. 数据准备:清洗、转换、索引
  2. 测试小样本:在小数据集上测试
  3. 监控性能:观察内存和CPU使用
  4. 渐进处理:分批处理大数据
  5. 结果验证:检查输出正确性

19.10 性能监控

19.10.1 日志分析

视图 > 面板 > 日志消息

19.10.2 渲染时间

# 获取渲染时间
canvas = iface.mapCanvas()
canvas.renderStarting.connect(lambda: print("开始渲染"))
canvas.renderComplete.connect(lambda: print("渲染完成"))

19.10.3 内存使用

import psutil

# 监控内存使用
process = psutil.Process()
print(f"内存使用: {process.memory_info().rss / 1024 / 1024:.2f} MB")

19.11 小结

本章介绍了QGIS性能优化方法:

关键要点

  1. 使用空间索引加速查询
  2. 简化几何和符号减少渲染负担
  3. 合理管理内存和资源
  4. 优化数据库查询
  5. 使用缓存提高网络性能
  6. 遵循最佳实践

性能优化是高效使用QGIS的关键。


上一章第18章 高级功能与扩展

下一章第20章 实战案例与项目应用

posted @ 2026-01-08 14:04  我才是银古  阅读(24)  评论(0)    收藏  举报