Mendix应用性能社区最佳实践
本文档由 Mendix 社区创建并为Mendix社区创建。它以“注意事项”和“注意事项”的形式收集性能最佳实践。应用程序必须具备的条件是性能良好。如果性能不好,用户将不会接受任何东西,而会选择替代品。本文描述了在开发过程中应用的一些最佳实践,以便获得性能更好的应用程序。可能需要进行负载测试和并有良好的测量工具,但这超出了本文档的范围。本文档包含涵盖Mendix Studio Pro,可以在其中考虑
目录
简介
本文档由 Mendix 社区创建并为Mendix社区创建。它以“注意事项”和“注意事项”的形式收集性能最佳实践。
应用程序必须具备的条件是性能良好。如果性能不好,用户将不会接受任何东西,而会选择替代品。本文描述了在开发过程中应用的一些最佳实践,以便获得性能更好的应用程序。
一切都应该尽可能简单,但不能简单。——爱因斯坦
过早优化是万恶之源。—— Donald Knuth
这两个名言都建议不要为了性能而使用困难的构造,除非真的需要它们并且已经研究过更简单的替代方案。可能需要进行负载测试和并有良好的测量工具,但这超出了本文档的范围。
其他最佳实践可能与性能最佳实践相冲突。例如,安全性可能需要事件处理程序,而性能需要最小化它们。良好的架构通常是不同质量方面之间的权衡。所以,做出积极的选择。
本文档包含涵盖Mendix Studio Pro,可以在其中考虑域模型(有一个关于索引的特殊部分)、微流和页面的性能。其他部分涵盖了Mendix领域特定语言(例如 XPath、expressions和 OQL)中特殊性能注意事项的部分基础设施。
领域模型的最佳实践
如果要对应用程序的领域模型进行简单合理的设计,应考虑以下几点:
- 为实体创建索引,可获得100以上的记录,并且可查询除Mendix引用/ID之外所有的。
- 尽量不使用计算属性,因为它们会在每次检索和列表的每行检索时触发。很少需要这种条件可见性。
- 尽量不使用事件句柄(event handler),因为它们会在每个事件(例如commit)触发。
- 尽量不使用引用集合关联。Mendix在每次查询时返回ID(列表查询的每行),因此,大量的引用,并且特别是引用集合将导致额外的查询,将导致额外的数据库负载。
- 如果数据卷变得太大,且并不总是需要时刻保留所有的数据,请考虑将数据归档。甚至可以创建两个相似的实体,一个包含当前使用的数据,另一个仅包含用作报表或其他历史原因的数据。
- 考虑使用反规范化的数据,这意味着将属性复制到其他的实体中。这样,数据每次不再从源实体中获取。如果数据改变不多,这样将节省大量的查询。但是,需要构建保持复制的属性同步的逻辑。
- 请勿对实体使用多层继承和太多的泛化,那将包含大量的数据,特别是使用XPath访问实体时,对大数据集会将泛化的安全规则添加给XPath而将产生复杂的查询,导致慢查询。请考虑以下替代方案:
- 在一个实体中组合属性,并添加枚举来决定它的泛化。
- 对于单个实体添加一对一关系的范型。根据UI需要,这些一对一关系可能是从专业化到泛化的正常引用,以节省预取时间。
- 通过业务逻辑,添加继承中的非持久化层来处理。
- 请勿对持久化实体使用临时关联。在屏幕/UI逻辑中使用非持久化实体。
- 在实体间避免使用多于一个的关系,特别是如果这类关系有不同的访问级别。相反,应该在其中某个实体中使用枚举,或者在实体间添加一个中介实体包含关联类型的枚举。例如,如果不同类型的用户访问一个文档,请勿创建Document_Owner、Document_Editor、Document_Viewer等,相反,请在实体间添加一个名为DocumentAccess的中介实体,该中介实体包含名为AccessType的枚举,其可能的值为Owner、Editor或者Viewer。
索引的最佳实践
在数据库界,索引是最佳实践长久的主题。对于Mendix应用,应采用以下最佳实践:
- 根据需要尽可能多创建索引。虽然每个索引都占用空间,而且
insert
、update
和delete
语句将变慢,但查询将受益匪浅。 - 由于Mendix取回对象的所有列,需要索引有两方面的原因。第一个原因是为了快速地获取唯一的Mendix内部的ID,第二个原因是为了排序。
- 在一个索引中,仅需要覆盖搜索语句和排序语句。
- 对于同一个属性开头的不必创建不同的索引。
- 根据经验,尽量减少索引列的数量。请保持在三个以下,最多使用五个。
- 请以最具选择性的属性开头,虽然需要考虑对单个属性的查询仅使用以该属性开头的索引。
- 索引只被用来匹配相等、一定范围的日期、数值查询,以及前导
/startsWith
的字符串查询。 - 索引扫描可发生在更复杂的语句如
contains
或者endsWith
中。这些仍比全表扫描快。
微流(Microflow)的最佳实践
- 最小化循环中的工作
- 如果提交列表,应在循环之后提交
- 如果需要,在循环之前创建名为_CommitList的列表,用来存放要提交的数据项。
- 对于循环中的查询,考虑在循环之前获取所有的数据,在循环内部再对该列表进行查找。
- 如果循环包含条件选择,请考虑决策逻辑是否可以是循环之前的最小化遍历的查询。
- 如果对象或列表可作为参数传递,请避免不必要的查询。
- 懂得并使用检索+聚合的优化。如果取回一个列表并对列表进行计数,Mendix将此优化为一个查询。如果在微流中在某些决策之后需要这个列表,明智的做法是再次检索数据,以便只获取所需的数据。这也适用于批处理,那样可以在单独的查询中对检索的总数进行优化,并取回检索块。
- 尽可能使用关联进行检索。这会使用缓存,更高的可读性,并使用索引。如果业务逻辑需要数据库值(因为通过关联的值可能会改变),那么数据库检索当然是必需的。
- 尽可能晚地提交。提交会对记录(或者记录列表)加锁。这意味着其他用户/逻辑需要对同一个对象进行提交的,必须等待前面的事务执行完成。
- 为了防止锁定,请执行小块提交数据的计划事件。这样数据就不会在更长的时间内被锁定。
页面的最佳实践
- 保持简洁。如果可能,分成多个页面。考虑移动App的逻辑,而不是一屏大而全的逻辑。
- 尽量减少发送的数据,例如使用分块或安全性来防止数据传输给客户端。
- 尽量避免多个相同的数据源,因为它们将多次加载对象。
- 最小化条件可见性。
- 给用户以反馈。如果这需要几秒以上的时间,请提供进度提示。
- 如果用户不必等待结果,请使用异步的方式。例如,通过界面发送邮件或者更新其他应用永远不应该是用户在UI中要等待的东西。对于异步执行,可选Mendix应用市场中的社区公共功能库(Community Commons Function Library )来在后台运行微流,或者使用任务队列来控制负载并防止后台工作高峰。
- 在表格组件(data grid)中使用某个属性过滤相关联的实体时,建议在下拉搜索字段中限制可能的选项,以便仅获取与表格中实体有关联的对象。例如,有一个Order实体的表格,添加下拉搜索框以按Order_Customer/Customer/Name进行过滤。将以下XPath约束添加到下拉搜索字段中将是有益的: [Order_Customer/Order]。这样,只有带有Order的Customer将在下拉搜索中可用。这是必要的,因为在某些数据库中,即使所有的索引都到位,过滤不存在的条件也很慢。
基础设施的最佳实践
- 获得更好的基础设施(例如,Mendix Cloud上更多的应用引擎)。
- 如果私有化部署,确保在Mendix之前配置web代理服务器来处理静态页面和压缩数据。
XPath的最佳实践
- 在XPath语句中,避免使用"不等于"和"not"语句。通常可以重写为肯定语句,比如:
<boolean>=false()
,<enumeration> = valueA,
<enumeration> = valueB
,integer>valueA
, 或者integer<valueB
。 - 如果查询逻辑允许,对同一个关联实体使用组合路径进行查询。
- 在老版本的PostgreSQL数据库中,使用属性开头的XPath是明智之举,因为数据库查询优化器按顺序处理语句。如今,据称查询优化器有所改善,这一规则不再需要。
- 确保所用的属性已建索引。
- 如果一个角色对于同一个实体有两个访问规则,一个提供只读访问权限,另一个提供读写访问权限,请勿让这些访问规则独占。请将只读规则包含读写规则。例如,如果访问级别基于布尔属性Editable,创建两个访问规则如下:第一保证对所有对象(无约束)的只读访问,第二保证对一些对象的读写访问(约束:
[Editable = true()]
)。请勿对第一个访问规则添加约束[Editable = false()]
,因为这样会在生成SQL时产生不必要的复杂性。
OQL的最佳实践
对于OQL,许多与XPath相同的最佳实践都适用。
注意:OQL查询不会安全地获取领域模型,因此可能需要在合适的时候添加额外的语句(例如,多租户应用程序中)
安全的最佳实践
- 尽量减少每个用户的角色数量
- 尽量减少每个实体的规则数量
Web服务和XML的最佳实践
- 使用SSHA256而不是BCrypt
- 对于schema的校验将减慢处理速度
- 对于微流使用子事务将减慢处理速度
MxAssist性能的最佳实践
MxAssist Performance Bot 有助于发现潜在的性能问题以进行改进。可以通过"View">"MxAssist Performance Bot"进行访问。
更详细的性能最佳实践,请参考Mendix最佳性能实践
更多推荐
所有评论(0)