Partilhar via


Otimização do código

À medida que as aplicações de tela evoluem para satisfazer diversos requisitos empresariais, o desafio de manter o desempenho ideal torna-se uma consideração crítica. As complexidades do processamento de dados, design da interface de utilizador e a funcionalidade nas aplicações de tela requerem uma abordagem com nuances à otimização do código.

À medida que as aplicações de tela se tornam mais complexas, os programadores encontram desafios relacionados com a recuperação de dados, a complexidade das fórmulas e as velocidades de composição. A necessidade de encontrar um equilíbrio entre funcionalidade robusta e interfaces de utilizador reativas ressalta a importância da adoção de uma abordagem sistemática para a otimização do código.

Power Fx otimização de fórmulas

Funções With

A função With avalia uma fórmula para um único registo. A fórmula pode calcular um valor e/ou realizar ações, como, por exemplo, modificar os dados ou trabalhar com uma ligação. Utilize With para melhorar a legibilidade de fórmulas complexas dividindo-as em subfórmulas com nomes mais pequenos. Estes valores nomeados funcionam como variáveis locais simples confinadas ao âmbito do With. A utilização de With tem preferência sobre variáveis globais ou de contexto, uma vez que é independente, fácil de compreender e pode ser utilizada em qualquer contexto de fórmula declarativa. Mais informações sobre a função With.

Uma captura de ecrã de uma Power Fx fórmula que utiliza a função With

Função Concurrent

A função Concurrent permite que várias fórmulas especificadas na mesma propriedade sejam avaliadas ao mesmo tempo se tiverem conector ou chamadas do Dataverse. Normalmente, múltiplas fórmulas são avaliadas ao serem encadeadas com o operador ; (ponto e vírgula), o qual avalia cada fórmula sequencialmente. Com a Concurrent função, a aplicação avaliará todas as fórmulas numa propriedade em simultâneo, mesmo depois de utilizar o ; operador. Esta simultaneidade ajuda os utilizadores a aguardar menos pelo mesmo resultado. Quando as chamadas de dados não são iniciadas até as chamadas anteriores serem concluídas, a aplicação tem de aguardar pela soma de todos os tempos de pedidos. Se as chamadas de dados forem iniciadas ao mesmo tempo, a aplicação só precisa de esperar pelo tempo do pedido mais longo. Mais informações sobre a função Concurrent.

Concurrent(
    ClearCollect(colAccounts1, Accounts),
    ClearCollect(colUsers1, Users),
    ClearCollect(colEnvDef1, 'Environment Variable Definitions'),
    ClearCollect(colEnvVal1, 'Environment Variable Values')
);

Função Coalesce

A função Coalesce avalia os argumentos por ordem e devolve o primeiro valor que não esteja em branco ou uma cadeia vazia. Utilize esta função para substituir um valor em branco ou uma cadeia vazia por um valor diferente, mas deixe os valores de cadeia não em branco e não vazios inalterados. Se todos os argumentos forem cadeias em branco ou vazias, a função volta a ficar em branco, tornando Coalesce uma boa forma de converter cadeias vazias em valores em branco.

Por exemplo:

If(Not IsBlank(value1), value1, Not IsBlank(value2), value2)

Requer que o valor 1 e o valor 2 sejam avaliados duas vezes. Esta função pode ser reduzida a:

Coalesce(value1, value2)

Função IsMatch

A função IsMatch testa se uma cadeia de texto corresponde a um padrão que pode ser composto por carateres comuns, padrões predefinidos ou uma expressão regular. Mais informações sobre a função IsMatch.

Por exemplo, esta fórmula corresponde a um Número de Segurança Social dos Estados Unidos:

IsMatch(TextInput1.Text, "\d{3}-\d{2}-\d{4}")

Explicação da expressão regular:

\\d Corresponde a qualquer dígito (0-9).

{3} Especifica que o padrão de dígitos anterior (\d) deve ocorrer exatamente três vezes.

- Corresponde ao caráter de hífen.

{2} Especifica que o padrão de dígitos anterior (\d) deve ocorrer exatamente duas vezes.

{4} Especifica que o padrão de dígitos anterior (\d) deve ocorrer exatamente quatro vezes.

Mais exemplos de IsMatch:

IsMatch(TextInput1.Text, "Hello World")
IsMatch(TextInput1\_2.Text, "(?!^\[0-9\]\\\*$)(?!^\[a-zA-Z\]\\\*$)(\[a-zA-Z0-9\]{8,10})")

Otimizar OnStart da aplicação

A propriedade OnStart para aplicações de tela desempenha um papel crucial na definição de ações que ocorrem quando a aplicação é iniciada. Esta propriedade permite que os programadores de aplicações executem tarefas de inicialização global, configurem variáveis e executem ações que só devem acontecer uma vez durante o processo de arranque da aplicação. Compreender e utilizar eficazmente a propriedade OnStart é essencial para criar aplicações de tela reativas e eficientes.

Uma abordagem recomendada é simplificar a App.OnStart função migrando configurações variáveis para fórmulas nomeadas. As fórmulas nomeadas, especialmente as configuradas no início do ciclo de vida da aplicação, revelam-se vantajosas. Estas fórmulas lidam com a inicialização de variáveis com base em chamadas de dados, fornecendo uma estrutura mais limpa e organizada para o seu código. Mais detalhes Criar aplicações de tela grandes e complexas — Power Apps | Microsoft Learn.

Nota

A propriedade OnStart é Imperativa. É uma lista ordenada de trabalho que precisa de ser feito antes que o primeiro ecrã seja mostrado. Por ser tão específico não apenas sobre o que precisa de ser feito, mas também quando esse trabalho tem de ser feito com base na ordem, limita a reordenação e o adiamento de otimizações que poderiam ser feitas de outra forma.

Ecrã inicial

Se App.OnStart contiver uma chamada de função Navigate, mesmo que esteja numa função If e raramente chamada, temos de concluir a execução da Aplicação. OnStart antes de mostrarmos o primeiro ecrã da aplicação.  App.StartScreen é a nova forma declarativa de indicar que ecrã deve ser mostrado primeiro, que não bloqueie otimizações.

A definição da propriedade StartScreen mostra o primeiro ecrã antes de App.OnStart ser concluído. App.StartScreen declares qual o objeto do ecrã a mostrar primeiro sem necessitar de qualquer pré-processamento.

Em vez de escrever código como:

App.OnStart = Collect(OrdersCache, Orders);
If(Param("AdminMode") = "1", Navigate(AdminScreen), Navigate(HomeScreen))

Alterar o código para:

App.OnStart = Collect(OrdersCache, Orders);
App.StartScreen = If(Param("AdminMode") = "1", AdminScreen, HomeScreen)

Consulte <https://Power Apps.microsoft.com/en-us/blog/app-startscreen-a-new-declarative-alternative-to-navigate-in-app-onstart/> para obter mais detalhes.

Aviso

Evite dependências entre StartScreen e OnStart. Referenciar uma fórmula nomeada que, por sua vez, referencia uma variável global, pode causar uma condição de corrida na qual StartScreen não é aplicada corretamente. Nota: não devemos ter dependências entre StartScreen e OnStart. Bloqueamos a referência a variáveis globais em StartScreen, mas podemos referenciar uma fórmula nomeada que, por sua vez, referencia uma variável global e que pode causar uma condição de corrida na qual StartScreen não é aplicado corretamente.

Fórmulas nomeadas

As fórmulas nomeadas são constantes ou estáticas que podem ser definidas na secção App.Formulas. Uma vez declarados em App.Formulas, podem ser utilizados em qualquer parte da aplicação e o seu valor permanece sempre atualizado. As Fórmulas nomeadas no Power Apps permitem a definição de valores ou conjuntos de valores que são automaticamente geridos e atualizados pela plataforma. Esta funcionalidade transfere a responsabilidade do cálculo de valor e manutenção do programador para Power Apps, simplificando o processo de desenvolvimento. As Fórmulas nomeadas no Power Apps são uma funcionalidade poderosa que pode melhorar significativamente o desempenho e a manutenção das aplicações.

As fórmulas nomeadas também abordar a declaração de temas de aplicações. Em muitos casos em que as aplicações empresariais são criadas, queremos que a aplicação tenha temas comuns para dar um aspeto e uma experiência de utilizador consistentes. Para criar um tema, existem dezenas e centenas de variáveis que precisam de ser declaradas em OnStart da Aplicação. Isso aumentou o comprimento do código e o tempo de inicialização do aplicativo.

Os controlos modernos também podem ajudar significativamente com a personalização e a reduzir a lógica escrita do cliente para processar personalizações. Os controlos modernos estão atualmente em pré-visualização.

Por exemplo, o código seguinte em App.OnStart pode ser movido para App.Formulas, reduzindo assim o tempo de arranque em declarações de variáveis globais.

Set(BoardDark, RGBA(181,136,99, 1));
Set(BoardSelect, RGBA(34,177,76,1));
Set(BoardRowWidth, 10);                      // expected 8 plus two guard characters for regular expressions.
Set(BoardMetadata, 8 \* BoardRowWidth + 1);   // which player is next, have pieces moved for castling rules, etc.
Set(BoardBlank, "----------------------------------------------------------------\_00000000000000");
Set(BoardClassic, "RNBQKBNR\_\_PPPPPPPP------------------------\_--------\_\_pppppppp\_\_rnbqkbnr\_\_0000000000");

O código pode ser movido para App.Formulas da seguinte forma:

BoardSize = 70;
BoardLight = RGBA(240,217,181, 1);
BoardDark = RGBA(181,136,99, 1);
BoardSelect = RGBA(34,177,76,1);
BoardRowWidth = 10;                      // expected 8 plus two guard characters for regular expressions
BoardMetadata = 8 \* BoardRowWidth + 1;   // which player is next, have pieces moved for castling rules, etc.
BoardBlank = "----------------------------------------------------------------\_00000000000000";
BoardClassic = "RNBQKBNR\_\_PPPPPPPP------------------------\_--------\_\_pppppppp\_\_rnbqkbnr\_\_0000000000";

Outro exemplo é em definir Lookups. Aqui, é necessária uma alteração numa fórmula de Procura para obter as informações de utilizador a partir do Office 365, em vez do Dataverse. Há apenas um lugar onde a alteração é necessária sem alterar o código em todos os lugares.

UserEmail = User().Email;
UserInfo = LookUp(Users, 'Primary Email' = User().Email);
UserTitle = UserInfo.Title;
UserPhone = Switch(UserInfo.'Preferred Phone', 'Preferred Phone (Users)'.'Mobile Phone', UserInfo.'Mobile Phone',
UserInfo.'Main Phone');

Estas fórmulas incorporam a essência do cálculo. Articulam o processo para determinar UserEmail, UserInfo, UserTitle e UserPhone com base noutros valores. Esta lógica é encapsulada, permitindo uma utilização generalizada em toda a aplicação, e pode ser modificada numa localização singular. A adaptabilidade estende-se à mudança da tabela Utilizadores do Dataverse para o conector do Office 365, sem necessitar de alterações às fórmulas espalhadas pela aplicação.

Outra abordagem é otimizar countRows.

varListItems = CountRows(SampleList)

Com a Função Set, a variável varListItems terá de ser inicializada com a contagem inicial de linhas na lista de amostras e definida novamente após os itens da lista terem sido adicionados ou removidos. Com fórmulas nomeadas, à medida que os dados mudam, as variáveis varListitems são atualizadas automaticamente.

As Fórmulas Nomeadas na propriedade App.Formulas fornecem uma abordagem mais flexível e declarativa para gerir valores e cálculos em toda a aplicação, o que oferece vantagens em termos de independência de temporização, atualizações automáticas, manutenção e definições imutáveis, em comparação com confiar apenas em App.OnStart.

Aspecto Fórmulas nomeadas (App.Formulas) App.OnStart
Independência de tempo As fórmulas ficam disponíveis instantaneamente e podem ser calculadas em qualquer ordem. As variáveis podem introduzir dependências de tempo, afetando a disponibilidade.
Atualizações Automáticas As fórmulas atualizam-se automaticamente quando as dependências mudam. As variáveis são definidas uma vez durante a inicialização; poderão ser necessárias atualizações manuais.
Capacidade de Manutenção Fórmulas centralizadas em um único local melhoram a capacidade de manutenção. Variáveis dispersas podem exigir descoberta e atualização em vários locais.
Definições imutáveis As definições de fórmula em App.Formulas são imutáveis. Valores de variáveis podem ser suscetíveis a alterações acidentais.

Funções definidas pelo utilizador

Funções definidas pelo usuário é uma funcionalidade experimental no Power Apps Authoring Studio que permite que os usuários criem sua própria função personalizada.

Para utilizar esta caraterística, em definições experimentais, selecione Novo motor de análise e Função Definida pelo utilizador (UDFs)

Defina uma fórmula em App.Formulas da seguinte forma:

FunctionName(Parameter1:DataType1, Parameter2:DataType2):OutputDataType = Formula

O código funciona assim:

  • FunctionName é utilizado para invocar a função

  • Parameter é o nome da entrada. É permitida uma ou mais entradas

  • DataType é um argumento transmitido para a função que tem de corresponder a este tipo de dados. Os tipos de dados disponíveis incluem Booleano, Cor, Data, Datetime, GUID, Hiperligação, Texto, Hora, Objeto sem tipo

  • OutputDataType é o tipo de dados em que a saída da função estará

  • Formula é a saída da função

// Function to calculate the area of a circle based on the radius
calcAreaOfCircle(radius: Number): Number = 
    IfError(Pi() * radius * radius, 0);

Utilize IfError para implementar o processamento de erros dentro da função definida.

Chame a função definida a partir do controlo de texto/etiqueta.

calcAreaOfCircle(Int(*TextInput1*.Text))

Nota

Esta é uma caraterística experimental e está sujeita a alterações. Alguns tipos de dados, como registos e filtros, ainda não são suportados.

Otimizar variáveis

As variáveis são utilizadas para definir e estabelecer valores locais e globais para serem utilizados em qualquer lugar nas aplicações. Embora sejam convenientes, muitos deles podem fazer com que a aplicação seja menos otimizada.

O exemplo a seguir demonstra a definição de uma variável para cada atributo de um objeto, o que requer a utilização de Set para cada propriedade.

Set(varEmpName, Office365Users.MyProfile().DisplayName);
Set(varEmpCity, Office365Users.MyProfile().City);
Set(varEmpPhone, Office365Users.MyProfile().BusinessPhones);
Set(varEmpUPN, Office365Users.MyProfile().UserPrincipalName);
Set(varEmpMgrName, Office365Users.ManagerV2(varEmpUPN).DisplayName);

Uma abordagem mais otimizada é usar a propriedade quando precisar:

Set(varEmployee, Office365Users.MyProfile())
"Welcome " & varEmployee.DisplayName

Utilize as variáveis de contexto e as variáveis globais de forma sensata. Se o âmbito de uma variável se expandir para além de um único ecrã, considere usar variáveis globais em vez de variáveis de contexto.

Demasiadas variáveis não utilizadas contribuem para aumentar a utilização da memória e para uma inicialização da aplicação ligeiramente mais lenta. Isto porque os recursos são alocados para estas variáveis, apesar de não serem utilizadas ativamente. Demasiadas variáveis não utilizadas também podem levar à complexidade geral da lógica da aplicação. Embora o impacto de variáveis não utilizadas possa não ser grave, é uma boa prática manter uma Power App limpa e bem organizada para garantir o desempenho ideal e a facilidade de desenvolvimento.

Otimizar coleções

As coleções são estruturas de armazenamento de dados temporários que podem ser utilizadas para armazenar e manipular dados dentro de uma Power Apps aplicação. No entanto, há uma linha tênue sobre quando as coleções podem levar a sobrecarga do desempenho. Portanto, limite o uso de coleções. Tente utilizá-las apenas quando for necessário.

// Use this pattern
ClearCollect(colErrors, {Text: gblErrorText, Code: gblErrorCode});

// Do not use this pattern
Clear(colErrors);
Collect(colErrors, {Text: gblErrorText, Code: gblErrorCode});

Para contar os registos numa coleção local, utilize CountIf em vez de Count(Filter()).

Considere esta orientação ao trabalhar com coleções:

Limite o tamanho e o número de coleções. Uma vez que as coleções são locais para a aplicação, são armazenadas na memória do dispositivo móvel. Quanto mais dados as coleções contiverem ou quanto maior o número de coleções, pior será o desempenho. Utilize a função ShowColumns para obter apenas as colunas específicas. Adicione a função Filter para obter apenas os dados relevantes.

A função de exemplo a seguir retorna o conjunto de dados completo.

ClearCollect(colDemoAccount, Accounts);

Compare com o código abaixo que vai retornar apenas registos e colunas específicos:

ClearCollect(colAcc,
              ShowColumns(
                Filter(Accounts, !IsBlank('Address 1: City')),
                "name","address1_city"))

O código de exemplo apresenta este conjunto de dados:

Uma captura de ecrã de um conjunto de dados com uma tabela chamada colAcc e duas colunas com dados, address1_city e nome

Defina uma frequência de atualização da origem de dados. Se estiver a adicionar novos registos à coleção, necessita de a atualizar ou de a recolher para obter os registos novos ou alterados na coleção. Se a sua origem de dados for atualizada por vários utilizadores, tem de atualizar a coleção para obter os registos novos ou alterados. Mais chamadas de atualização significam mais interação com o servidor.

Armazenar dados em cache em coleções e variáveis

Uma coleção, essencialmente uma variável de tabela, é distinta na medida em que armazena linhas e colunas de dados em vez de um único item de dados. A sua utilidade está associada a duas finalidades principais: em primeiro lugar, para agregar dados antes de os transmitir à origem de dados e, em segundo lugar, para armazenar informações em cache, eliminando a necessidade de consultas frequentes à origem de dados. Uma vez que as coleções se alinham com a estrutura tabular da origens de dados e do Power Apps, oferecem um meio eficiente de interagir com os dados, mesmo em cenários offline.

// Clear the contents of EmployeeCollection, it already contains data
ClearCollect(
    colEmployee,
    {
        Id: "1",
        Name: "John",
        Department: "IT"
    },
    {
        Id: "2",
        Name: "Nestor",
        Department: "IT"
    }
)

Remover variáveis e suportes de dados não utilizados

Embora a multimédia e as variáveis não utilizadas possam não criar um impacto drástico no desempenho da aplicação, é importante limpar a sua aplicação de quaisquer multimédia ou variáveis não utilizadas.

  • Os ficheiros multimédia não utilizados contribuem para o aumento geral do tamanho da aplicação. Isto pode levar a tempos de carregamento mais lentos das aplicações.

  • As variáveis não utilizadas contribuem para um maior uso da memória e uma inicialização ligeiramente mais lenta da aplicação. Isto porque os recursos são alocados para estas variáveis, apesar de não serem utilizadas ativamente. Além disso, demasiadas variáveis não utilizadas podem levar a uma maior complexidade geral da lógica da aplicação.

  • Utilize o Verificador de Aplicações para rever multimédia e variáveis não utilizadas.

Otimizar ecrãs e controlos

Evitar referências cruzadas entre controlos

Os controlos que referenciam controlos noutros ecrãs podem abrandar o carregamento e a navegação da aplicação. Isto pode forçar a aplicação a carregar os outros ecrãs imediatamente, em vez de aguardar até que o utilizador navegue para esse ecrã. Para resolver este problema, utilize variáveis, coleções e contexto de navegação para partilhar o estado nos ecrãs.

O verificador de Aplicações do Power Apps no estúdio de criação mostra controlos com referências cruzadas. Reveja regularmente o Verificador de aplicações para resolver este problema.

Segue-se um exemplo de controlos de referência cruzada. Na imagem abaixo, é feita referência cruzada dos controlos Galeria 1 no controlo Ecrã 2, Etiqueta.

Uma captura de ecrã do Power Apps Studio a mostrar um controlo com referências cruzadas

Se referenciar um controlo do primeiro ecrã na aplicação no segundo ecrã, não haverá qualquer impacto no desempenho, uma vez que o primeiro ecrã já foi carregado e isto pode realmente ser uma vantagem, pois a aplicação é declarativa em vez de utilizar variáveis.

Se referenciar controlos que ainda não foram carregados, como o primeiro ecrã que referencia um controlo chamado Label 3 do ecrã 3, será necessário carregar o ecrã na memória.

Ativar DelayOutput para controlos de texto

Definição de saída de atraso Quando definido como true, a intervenção do utilizador fica registada após meio segundo de atraso. Útil para adiar operações dispendiosas até que o utilizador conclua a introdução de texto, como para filtragem quando a introdução é utilizada noutras fórmulas.

Por exemplo, para uma Galeria cujos Itens são Filtrados dependendo do que é introduzido no controlo TextInput:

  • Com DelayOutput definido como false, que é a predefinição, a Galeria é filtrada assim que qualquer texto é escrito. Se você tiver uma galeria com muitos itens, recarregar a Galeria com alterações imediatamente diminuirá o desempenho; seria mais vantajoso esperar um pouco. Isto é prático quando estiver a utilizar TextInput para uma cadeia de pesquisa (Consulte Pesquisar ou as novas funções StartsWith).

  • Com DelayOutput definido como true, existe um segundo atraso antes de as alterações serem detetadas. Isso é feito para que você tenha tempo para terminar de digitar o que deseja. O atraso funciona bem quando usado para ajudar a propriedade TextInput.OnChange. Se tiver ações associadas a alterações, não quer que sejam acionadas até que tudo o que pretende seja escrito no campo.

Delegação e processamento do lado do servidor

Delegação

A delegação no Power Apps é um conceito que se refere à capacidade da aplicação de descarregar certas operações para a origem de dados subjacente, em vez de processar as operações no Power Apps. Ao utilizar a delegação Power Apps, os programadores podem criar aplicações mais eficientes e dimensionáveis com um bom desempenho, mesmo em cenários que envolvam grandes conjuntos de dados. É importante estar ciente das limitações de delegação para operações e origens de dados específicas e conceber aplicações em conformidade para obter um desempenho ideal.

![NOTA] Nem todas as funções são delegáveis. Consulte Compreender a Delegação para obter mais informações sobre a delegação.

A delegação tem várias vantagens, como a otimização de consultas e adiciona suporte para grandes conjuntos de dados. Além disso, se os dados de origem mudarem frequentemente, a delegação ajuda a manter os dados atualizados.

Reduzir chamadas à API para a origem de dados

Por vezes, pode ser conveniente seguir apenas práticas de codificação, tais como criar coleções através da realização de associações dentro da aplicação de tela. Consulte o código abaixo:

Neste exemplo, há duas tabelas, Motoristas e Camiões. O programador escreve o código para criar uma coleção de detalhes de motoristas e de camiões e, para cada camião, estão a chamar os motorista que possuem os camiões.

// Bad code
ClearCollect(vartruckdata, AddColumns('Truck Details',
    "CITY",LookUp(Drivers, 'Truck Details'\[@'Dummy ID'\] = Drivers\[@'Truck Details'\],City),
        "FIRSTNAME",LookUp(Drivers, 'Truck Details'\[@'Dummy ID'\] = Drivers\[@'Truck Details'\],'Driver First Name'),
    "LASTNAME",LookUp(Drivers, 'Truck Details'\[@'Dummy ID'\] = Drivers\[@'Truck Details'\],'Driver Last Name'),
        "STATE",LookUp(Drivers, 'Truck Details'\[@'Dummy ID'\] = Drivers\[@'Truck Details'\],State)));

A execução destas operações de associação a partir da aplicação de tela pode gerar inúmeras chamadas para a origem de dados, o que leva a tempos de carregamento muito lentos.

Uma abordagem melhor é:

// Good code
Set(
    varTruckData,
    LookUp(
        Drivers,
        'Dummy ID' = ThisRecord.'Dummy ID',
        'Driver First Name'
    ) & LookUp(
        Drivers,
        'Dummy ID' = ThisRecord.'Dummy ID',
        'Driver Last Name'
        )
);

Set(
    varTruckData,
    With(
        {
            vDriver: LookUp(
                Drivers,
                'Dummy ID' = ThisRecord.'Dummy ID'
            )
        },
        vDriver.'Driver First Name' & vDriver.'Driver Last Name'
    )
)

No cenário em tempo real, é possível reduzir os tempos de carregamento de 5 minutos para menos de 10 segundos ao corrigir apenas os dados ao nível da origem de dados.

Processamento do lado do servidor

Diferentes origens de dados, como SQL e Dataverse, permitem-lhe delegar o processamento de dados, como Filtro e Procuras, para a origem de dados. No SQL Server, os utilizadores podem criar vistas, as quais têm conteúdo definido por uma consulta. Da mesma forma, com o Dataverse, os utilizadores podem criar plug-ins de low-code para escrever lógica para processamento de dados do lado do servidor e só obter os resultados finais em aplicações de tela.

A delegação do processamento de dados ao servidor pode melhorar o desempenho geral, reduzir o código do lado do cliente e são fáceis de manter.

Mais informações sobre plug-ins no Dataverse.

Otimizar padrões de dados de consulta

Utilizar seleção de colunas explícita

A caraterística Seleção Explícita de Coluna (ECS) está ativada por predefinição para todas as novas aplicações. Se não estiver ativada para a sua aplicação, deve ativá-la. O ECS reduz automaticamente o número de colunas obtidas apenas para aquelas usadas na aplicação. Se a ECS não estiver ativada, poderá obter mais dados do que precisa, o que pode afetar o desempenho. Ocasionalmente, quando uma aplicação extrai dados através de coleções, a linhagem original ou a origem de uma coluna pode ser perdida. Não sabemos se está a sendo usada e deixamos de a usar na ECS. Normalmente, pode forçar o ECS a trabalhar para uma coluna em falta utilizando a expressão ShowColumns do PowerFx após uma referência de coleção ou utilizando-a num controlo.

Evitar chamar o Power Automate para preencher uma coleção

Uma prática comum é utilizar o Power Automate para obter e preencher coleções no Power Apps. Embora esta abordagem seja válida, existem situações em que poderá não ser a escolha mais eficiente. A chamada ao Power Automate vem com uma sobrecarga de latência de rede e adiciona um custo de desempenho de 0,6 segundos para instanciar o fluxo do Power Automate.

A utilização excessiva de fluxos do Power Automate também pode levar a limites de execução e a limitações. Portanto, sempre avalie as compensações entre a latência da rede e o custo de desempenho.

Eliminar o problema N+1

O problema N+1 é um problema comum em consultas de base de dados onde, em vez de obter todos os dados necessários numa única consulta, são feitas várias consultas adicionais para obter dados relacionados. Isto pode levar a problemas de desempenho, uma vez que cada consulta adicional incorre em sobrecarga.

Uma simples chamada como esta para carregar uma coleção, pode gerar chamadas N+1 para a origem de dados.

ClearCollect(MyCollection, OrdersList,
    {
        LookUp(CustomersList,CustomerID = OrdersList[@CustomerID])
    }
)

No contexto de aplicações de tela e galerias, o problema N+1 pode surgir ao trabalhar com origens de dados e galerias que apresentam registos relacionados. O problema ocorre normalmente quando são feitas mais consultas para cada item apresentado na galeria, levando a um estrangulamento de desempenho.

Utilize Ver objetos no SQL Server para evitar problemas de consulta N+1 ou altere a interface de utilizador para evitar acionar o cenário N+1.

Dataverse obtém automaticamente os dados necessários de tabelas relacionadas e pode selecionar as colunas a partir de tabelas relacionadas.

ThisItem.Account.'Account Name'

Se o tamanho de RelatedDataSource for pequeno (<500 registos), pode colocá-lo em cache numa coleção e utilizar a coleção para fomentar o cenário de consulta de Procura (N+1).

Limitar o tamanho do pacote

Apesar de o Power Apps fazer muito para otimizar o carregamento de aplicações, pode tomar medidas para reduzir a pegada das suas aplicações. Uma pegada reduzida é especialmente importante para usuários de dispositivos mais antigos ou usuários em localidades onde há maior latência ou largura de banda reduzida.

  • Avalie os conteúdos multimédia incorporados na sua aplicação. Se algo não for utilizado, elimine-o.

  • As imagens incorporadas poderão ser demasiado grandes. Em vez de ficheiros PNG, veja se pode utilizar imagens SVG. No entanto, tenha cuidado ao usar texto em imagens SVG, porque a fonte usada terá que ser instalada no cliente. Uma solução ótima quando precisa de mostrar texto é sobrepor uma etiqueta de texto a uma imagem.

  • Avalie se a resolução é adequada para o fator de forma. A resolução para uma aplicação móvel não precisa de ser tão alta como a resolução para uma aplicação de ambiente de trabalho. Experimente para obter o equilíbrio certo entre qualidade e tamanho da imagem.

  • Se tiver ecrãs não utilizados, elimine-os. Tenha cuidado para não eliminar quaisquer ecrãs ocultos que só os criadores de aplicações ou administradores utilizam.

  • Avalie se está a tentar encaixar demasiados fluxos de trabalho numa única aplicação. Por exemplo, tem ecrãs de administração e de cliente na mesma aplicação? Em caso afirmativo, considere dividi-las em aplicações individuais. Esta abordagem também facilitará o trabalho de várias pessoas nas aplicações ao mesmo tempo e limita a "área de impacto" (quantidade de testes) quando as alterações à aplicação exigirem uma aprovação de teste completa.

Otimizar ForAll

A função ForAll em Power Apps é utilizada para iterar através de uma tabela de registos e aplicar uma fórmula ou conjunto de fórmulas a cada registo. Embora a função em si seja versátil, a utilização inadequada da função ForAll pode rapidamente afetar negativamente o desempenho da sua aplicação.

A função ForAll é uma função sequencial singular em vez de uma função concorrente. Por conseguinte, analisa apenas um registo de cada vez, obtém o resultado e, em seguida, continua para o seguinte até passar por todos os registos no respetivo âmbito.

Evite o Aninhamento de ForAll a todo custo. Isto pode levar a iterações exponenciais e afetar significativamente o desempenho.

ClearCollect(FollowUpMeetingAttendees.ForAll(ForAll(Distinct(AttendeesList.EmailAddress.Address).Lookup(Attendees))))

Atualizações em lote para o banco de dados

ForAll + Patch pode ser uma abordagem para atualizar o banco de dados em lote. No entanto, tenha cuidado com a utilização da ordem de ForAll e Patch.

A função seguinte:

Patch(SampleFoodSalesData, ForAll(colSampleFoodSales,
    {
        demoName:"fromCanvas2"
    })
);

Tem melhor desempenho do que:

ForAll(colSampleFoodSales, Patch(SampleFoodSalesData,
    {
        demoName:"test"
    })
);

Próximo passo