# 优化应用程序性能

应用程序性能可以通过减小应用程序大小、简化数据模型以及战略性地使用集合分析来提高。本部分将指出可能影响性能的领域，以及如何评估和监控应用程序性能，从而帮助您避免性能问题。

您可以使用性能评估工具监控应用程序的性能，还可以通过手动分配更大的引擎来测试其在不同引擎大小下的性能。有关更多详细信息，请参见 [应用程序性能评估](https://help.qlik.com/zh-CN/cloud-services/Subsystems/Hub/Content/Sense_Hub/Apps/app-performance-evaluation.htm) 和 [分配引擎以提高应用程序性能](https://help.qlik.com/zh-CN/cloud-services/Subsystems/Hub/Content/Sense_Hub/Apps/app-performance-select-engine.htm)。

## 应用程序复杂性

这些是可帮助诊断问题的宽泛类别。 最复杂的应用程序性能最低。

简单的应用程序：

* 不包含复杂的集合分析或 If() 语句。
* 不包含大型表。
* 具有简单的数据模型。
* 包含简单的计算。
* 可能具有大数据量。

中等复杂的应用程序：

* 具有包含许多表的数据模型，但遵循最佳实践。
* 使用集合分析和多个 If() 语句。
* 在工作表上具有大型或宽表（15 列或更多）。

复杂的应用程序：

* 具有非常复杂的数据模型。

* 连接到大数据量。

* 包含复杂的计算、图表和表。

## 大数据量

连接到大数据量时，您可以采用这些架构策略。

### 分段

您可以按时间范围、区域或聚合级别等维度对 QVDs 进行分段。例如，您可以有：

* 包含最近两年数据的 QVD。

* 包含超过两年历史数据的 QVD。

* 包含在更高级别聚合的所有数据的 QVD。例如，按月而不是按日期，或按国家/地区而不是按单个客户。

* 包含所有数据的一个大型 QVD，仅由一小部分用户使用。

您可以以类似的方式对应用程序进行分段。较小的应用程序将满足大多数用户的分析需求。这可以节省内存。

您还可以拥有专注于不同区域的多个应用程序。这样，用户就不会打开包含他们不感兴趣或无权访问的数据的应用程序。无法通过部分访问访问的数据仍然会影响内存。

### 按需生成应用程序 (ODAG)

Qlik Sense 按需应用程序为用户提供大数据存储的聚合视图。他们可以识别并加载数据的相关子集以进行详细分析。

从用户的角度来看，有两个应用程序：

1. 包含聚合数据的购物车。
2. 用于显示详细信息的空模板应用程序。

用户在购物车应用程序中进行选择。一旦达到阈值，就会创建一个自定义 LOAD 脚本，该脚本使用请求的详细信息填充模板应用程序。 有关更多信息，请参见 [通过 On-demand 应用程序管理大数据](https://help.qlik.com/zh-CN/cloud-services/Subsystems/Hub/Content/Sense_Hub/DataSource/Manage-big-data.htm)。

### 应用程序链接

应用程序链接（在 QlikView 中称为文档链接）意味着存在一个用户定期使用的聚合应用程序。 如果用户需要更多详细信息，可以将选择从聚合应用程序传递到详细信息应用程序，以便他们可以查看更低级别的粒度。这可以节省内存，因为用户不会加载不必要的详细信息。可以通过向工作表添加按钮对象来执行应用程序链接。 有关更多信息，请参见 [应用程序链接](https://help.qlik.com/zh-CN/cloud-services/Subsystems/Hub/Content/Sense_Hub/Visualizations/Button/create-buttons.htm#Applicat)。

还通过 APIs 支持应用程序链接。例如，您可以使用 应用程序集成 API 创建自定义应用程序链接。有关更多信息，请参见 [应用程序集成 API](https://help.qlik.com/zh-CN/sense-developer/May2026/Subsystems/APIs/Content/Sense_ClientAPIs/app-integration-api.htm) （仅提供英文版本）。

### 动态视图

动态视图可为高数据量或快速变化的数据场景提供最新的可视化。使用动态视图时，请考虑以下事项：

* 更新动态视图时，将直接加载数据源。更新性能受底层数据源性能的影响。

* 动态视图模板应用程序可以帮助您创建动态图表。

有关使用动态视图的更多信息，请参见 [使用动态视图管理数据](https://help.qlik.com/zh-CN/cloud-services/Subsystems/Hub/Content/Sense_Hub/DynamicViews/dynamic-views.htm)。

### Direct Query

虽然建议使用内存中应用程序，但 Direct Query 允许您将数据保留在其原始源中。请考虑以下事项以优化您的 Direct Query 使用：

* Direct Query 的性能在很大程度上受底层数据源性能的影响。

* 保持您的 Direct Query 数据模型尽可能简单，因为复杂的查询可能会导致性能问题。

有关 Direct Query 的更多信息，请参见 [使用 Direct Query 直接访问云数据库](https://help.qlik.com/zh-CN/cloud-services/Subsystems/Hub/Content/Sense_Hub/DirectQuery/direct-access-with-direct-query.htm)。

## 数据模型性能

以下是可影响数据模型性能的指标。每一个都是将改善应用程序可用性的最佳实践。

数据模型性能最佳实践

| 操作 | 描述 |
| --- | --- |
| 删除合成钥 | 在两个或更多数据表共有两个或更多字段时，Qlik Sense 会创建合成钥。这可能意味着脚本或数据模型中存在错误。要诊断合成钥，请参阅[合成钥](https://help.qlik.com/zh-CN/cloud-services/Subsystems/Hub/Content/Sense_Hub/Scripting/synthetic-keys.htm)。 |
| 从数据模型删除循环引用 | 当两个字段具有多个关联时，会发生循环引用。Qlik Sense 将尝试通过更改与其中一个表格之间的连接来解决这些问题。但是，所有循环引用警告都应得到解决，请参阅[了解并解决循环引用](https://help.qlik.com/zh-CN/cloud-services/Subsystems/Hub/Content/Sense_Hub/LoadData/understand-circular-references.htm)。 |
| 适当的数据粒度 | 您应当只加载必要的数据。例如：用户组仅需要按周、月和年划分的数据。您可在聚合的数据中加载，或在加载脚本中聚合数据以节省内存。如果用户确实需要可视化粒度级别较低的数据，可使用 ODAG 或文档链接。 |
| 尽可能使用 QVDs | QVD 文件包含从 Qlik Sense 中导出的数据表。此文件格式在从脚本读取数据时已针对速度进行了优化，但仍非常紧凑。从 QVD 文件读取数据通常比从其他数据源读取快 10 到 100 倍。有关更多信息，请参阅[使用 QVD 文件](https://help.qlik.com/zh-CN/cloud-services/Subsystems/Hub/Content/Sense_Hub/Scripting/work-with-QVD-files.htm)。 |
| 在加载时优化 QVD 文件 | QVD 文件可以用两种模式读取：标准（快速）和优化（超快）。所选模式由脚本引擎自动确定。<br><br>对于优化的加载存在一些限制。可重命名字段，但任何这些操作将导致标准加载：<br><br><ul><li>加载的字段上的任何转换。 </li><li>使用 <span>where</span> 子句使得 <span>Qlik Sense</span> 将记录解压。 </li><li>在加载的字段上使用<span>映射</span>。</li></ul> |
| 利用增量加载 | 如果您的应用程序连接到来自不断更新的数据库的大量数据，则重新加载整个数据集可能会非常耗时。您应当改为使用增量加载，以在数据库中检索新的或已更改的记录。有关详细信息，请参阅[加载新的和更新的记录与增量加载](https://help.qlik.com/zh-CN/cloud-services/Subsystems/Hub/Content/Sense_Hub/LoadData/use-QVD-files-incremental-load.htm)。 |
| 合并 Snowflake 模型 | 如果您有 Snowflake 数据模型，将能够通过使用 Join 前缀或其他映射联接它们中的一些来减少数据表的数目。这对于大型事实表尤其重要。一个好的经验法则是只有一个大型表。有关详细信息，请参阅[联接或不联接](https://community.qlik.com/t5/Qlik-Design-Blog/To-Join-or-not-to-Join/ba-p/1463102)。 |
| 将具有较少字段数的表格去规范化 | 如果您有两个包含字段很少的表格，将它们合并可能会提升性能。 有关详细信息，请参阅[使用 Join 和 Keep 合并表格](https://help.qlik.com/zh-CN/cloud-services/Subsystems/Hub/Content/Sense_Hub/Scripting/combine-tables-with-join-keep.htm)。 |
| 采用映射加载的去规范化查找（叶）表格 | 如果您只需要将字段从一个表格添加到另一个表格，则不应当使用 Join 前缀。您应当使用 ApplyMap 查找函数，请参阅[不要联接 - 使用 ApplyMap](https://community.qlik.com/t5/Qlik-Design-Blog/Don-t-join-use-Applymap-instead/ba-p/1467592)。 |
| 将时间戳删除或与日期字段分离 | 当时间戳出现时，日期字段可能会填满空间，因为字符串表示更大，且不同值的数目更大。如果您的分析不需要精度，您可以使用 Timestamp(Floor(YourTimestamp,1/24)) 将时间戳舍入到最近的小时，或者使用 Date(Floor(YourTimestamp)) 完全删除时间组件。<br><br>如果您需要时间戳，可将其与日期本身分离。您可以使用相同的 Floor() 函数，然后通过使用类似以下内容来创建包含提取时间的新字段：Time(Frac(YourTimestamp))。 |
| 从数据模型删除不必要的字段 | 您应当仅在数据模型中加载必要的字段。避免使用 Load \* 和 SELECT。确保您保留：<br><br><ul> <li>对于分析必要的字段。</li> <li>实际在应用程序中使用的字段。 </li> </ul> |
| 在处理大量数据时避免链接表格 | 您应当尽可能使用链接表格。但是，如果您处理大量数据，串联表格可能优于链接表格。 |
| 串联维度分解为新的字段 | 您应当将串联的维度分解成单独字段。这样会减少在您的字段中唯一值的发生次数。这与时间戳的优化方式相似。 |
| 尽可能使用 AutoNumber | 您可创建优化负载，方法是先从 QVD 文件将数据载入，然后使用 AutoNumber 语句将值转换为符号键。 有关详细信息，请参阅[AutoNumber](https://help.qlik.com/zh-CN/cloud-services/Subsystems/Hub/Content/Sense_Hub/Scripting/ScriptRegularStatements/Autonumber.htm)。 |
| 避免数据岛 | 数据岛可能会有用，但通常会影响性能。如果您为选择项值创建岛，则使用变量。 |
| 基于增量时间范围存储 QVD | 您应当分段存储 QVD，如每月。这些较小的月度 QVD 可支持许多可能不需要所有数据的不同应用程序。 |

## 工作表性能

这些是可提高工作表和可视化性能的最佳实践。

工作表性能最佳实践

| 操作 | 描述 |
| --- | --- |
| 尽可能避免使用 If() 函数 | 如果在聚合函数内部使用 If() 函数，它将在记录级别运行并被评估多次。<br><br>例如，如果在聚合中有 1000 条记录，则 If() 条件将被评估 1000 次。如果嵌套语句，这可能会迅速级联。您应该改用集合分析。集合分析过滤器在聚合之前应用，从而产生更快的响应。这些响应也可以通过集合分析进行缓存，而 If() 则不能。<br>您还可以考虑其他函数和对数据模型的修改。 |
| [](https://help.qlik.com/en-US/cloud-services/Subsystems/Hub/Content/Sense_Hub/Apps/app-performance.htm)尽可能避免在聚合表内部使用来自不同表的字段。 | 评估聚合时，计算将经历两个步骤：<br><br><ol> <li> <p>第一步是找到要进行计算的相关组合。此步骤是单线程的。</p> </li> <li> <p>第二步是执行计算。此步骤是多线程的。</p> </li> </ol><br><br>单线程部分会极大地影响性能。<br>一个例子是，如果在聚合内部有多个字段，例如 Sum(Quantity\*ListPrice)。如果 Quantity 在事实表中，而 ListPrice 在主产品表中，则引擎首先需要连接这两个表以找到组合，然后才能开始对乘积求和。连接是单线程部分，求和是多线程的。<br>如果两个字段都在同一个表中找到，则不需要连接，并且聚合的评估速度会快得多。 |
| 尽量少用 Aggr() 和嵌套的 Aggr() 函数 | Aggr() 函数会极大地影响性能。不正确的使用可能会给出不准确的结果。例如，在具有与 Aggr() 函数内部的维度不同的维度的表中。有关更多信息，请参见 [When should AGGR not be used?](https://community.qlik.com/t5/Qlik-Design-Blog/When-should-the-Aggr-function-NOT-be-used/ba-p/1467855) |
| 尽可能使用集合分析 | 您可以使用集合分析来定义一组不同于当前选择定义的正常集合的数据值。有关更多信息，请参见 [集合分析](https://help.qlik.com/zh-CN/cloud-services/Subsystems/Hub/Content/Sense_Hub/ChartFunctions/SetAnalysis/set-analysis-expressions.htm)。 |
| 尽可能避免字符串比较 | 字符串比较不如集合分析有效。例如，您应该避免使用 Match()、MixMatch()、WildMatch() 和 Pick()。在脚本中创建标志或改用集合分析。 有关更多信息，请参见 [条件函数](https://help.qlik.com/zh-CN/cloud-services/Subsystems/Hub/Content/Sense_Hub/Scripting/ConditionalFunctions/conditional-functions.htm) 和 [Performance of conditional aggregations](https://community.qlik.com/t5/Qlik-Design-Blog/Performance-of-Conditional-Aggregations/ba-p/1463021)。 |
| 在包含密集计算的对象上使用计算条件 | 当没有选择时，您可能拥有包含许多记录的可视化。作为最佳实践，向对象添加计算条件，以便它们仅在进行某些选择后才呈现。这可以阻止创建非常大的超立方体。例如：GetSelectedCount([Country])=1 OR GetPossibleCount([Country])=1。在这种情况下，除非用户选择单个国家/地区，或进行其他仅可能有一个国家/地区的选择，否则不会呈现可视化。 |
| 尽可能在脚本中预先计算度量 | 任何处于数据模型最低粒度级别的度量都应在脚本中计算。例如，如果在表中的同一记录中具有 Sales 和 Cost，则可以通过计算 Sales - Cost AS Margin 来得出利润率。如果您知道其他值不会根据选择而变化，或者它们绑定到不同的粒度级别，您也可以提前聚合这些值。 |
| 表少于 15 列并具有计算条件 | 具有 15 列的表可被视为宽表。如果您的表包含许多记录，则应在表对象上使用计算条件，以便它仅在满足某些选择或条件后才呈现。如果您的表非常宽，请考虑：<br><br><ul> <li> 创建多个有条件显示的小表。</li> <li> 使用有条件显示列的方法。</li> <li> 使您的表仅限于分析所需的字段。</li> </ul> |
| 工作表没有过多的对象 | 当用户导航到工作表时，将计算对象。每次用户在该工作表上进行选择时，如果缓存中不存在该当前状态，则将重新计算每个对象。如果您有一个包含许多图表的工作表，则用户将不得不在几乎每次选择时等待每个对象进行计算。这给引擎带来了巨大的负载。作为最佳实践，请遵循 Dashboard/Analysis/Reporting (DAR) 概念来开发干净且极简的应用程序。有关更多信息，请参见 [DAR methodology](https://community.qlik.com/t5/Qlik-Design-Blog/DAR-methodology/ba-p/1466733)。 |
| 在脚本中利用数字标志以用于集合分析 | 带有标志的集合分析可能比使用字符串比较或乘法更有效。 |
| [](https://help.qlik.com/en-US/cloud-services/Subsystems/Hub/Content/Sense_Hub/Apps/app-performance.htm)用于表达式的主条目或变量 | 主条目支持受控指标的拖放，并保证表达式将被缓存。例如，Sum(Sales) 不同于 SUM(Sales)。表达式根据拼写和大小写进行缓存，并且需要逐字匹配才能被重用。 |

## 数据加载性能

优化数据加载对于在 Qlik Cloud 中使用应用程序时获得无缝且响应式的体验非常重要。本部分重点介绍了影响性能的因素，并提供了有关如何防止性能问题的指导。

### Qlik Data Gateway - Direct Access

当您使用 Qlik Data Gateway - Direct Access 将数据重新加载到您的应用程序中时，以下因素会影响性能：

* 托管 Data Gateway 的计算机与数据库之间的连接速度和延迟。

* 托管 Data Gateway 的计算机与您的 Qlik Cloud 租户之间的连接速度和延迟。理想情况下，将 Data Gateway 托管在与您的 Qlik Cloud 租户相同的区域中，以提高性能。

### 数据库存储

缓慢的存储连接会增加重新加载时间。对于托管在本地或云中的数据库，请考虑以下事项：

* 本地：如果您的数据库在本地并与其他应用程序共享服务器，其性能可能会受到这些其他应用程序活动的影响。

* 云：如果大小合适，云数据库通常比本地数据库提供更好的性能。为了获得最佳结果，请为您的云存储选择一个靠近您的 Qlik Cloud 租户的区域。