0 Seguidores · 96 Postagens

SQL é uma linguagem padrão para armazenar, manipular e recuperar dados em bancos de dados relacionais.

Anúncio Danusa Calixto · Nov. 29, 2023

Olá Desenvolvedores, 

Nossa próxima Mesa Redonda de Desenvolvedores online irá acontecer no dia 30 de Novembro de 2023 às 10 am ET | 4pm CET. 📍 

Conversas sobre tecnologia:

1. Foreign Tables - by @Benjamin De Boe Manager, Analytics Product Management, InterSystems
2. Construindo "data products" com dbt e InterSystems IRIS - by @Thomas Dyar Product Manager, Machine Learning, InterSystems

Teremos tempo para perguntas e discussão aberta: 

>> RSVP através Global Masters challenge <<

 

0
0 54
Artigo Danusa Calixto · Nov. 28, 2023 8m read

Visão geral

A documentação online contém o tópico Defining and Using Class Queries (Definir e usar consultas de classe) para referência-

A personalização direta de procedimentos armazenados com ObjectScript tem sido útil para acessar o armazenamento NoSQL e as mensagens externas pela integração, para apresentar a saída em um formato tabular.

Por exemplo: um aplicativo que já usa 90% da interação SQL de um front-end também pode estender esse acesso aos outros 10% da funcionalidade de plataforma necessária, pelo mesmo acesso SQL.

A finalidade deste artigo é explorar como alcançar o mesmo efeito usando os métodos do Embedded Python.

Figura 1: procedimento armazenado como um SQL gateway para outra funcionalidade de plataforma

Demonstração

Para esse exemplo, foi definido o seguinte armazenamento NoSQL:

^alwo.IndexBook("A",1)="abc"
^alwo.IndexBook("A",2)="def"
^alwo.IndexBook("B")=""
^alwo.IndexBook("C")=""
^alwo.IndexBook("D",1)="gef"
^alwo.IndexBook("E",1)="ijk"
^alwo.IndexBook("E",2)="lmn"

Para teste, o procedimento armazenado pode ser executado em um terminal:

GBI>Do $SYSTEM.SQL.Shell()
SQL Command Line Shell
----------------------------------------------------
 
The command prefix is currently set to: <<nothing>>.
Enter <command>, 'q' to quit, '?' for help.

[SQL]GBI>>call alwo.PyProcTest_GetNotes('A')

Dumping result #1
Tab     NoteId  NoteText
A       1       abc
A       2       def
B       0
C       0
D       0
E       0
 
6 Rows(s) Affected
statement prepare time(s)/globals/cmds/disk: 0.0003s/4/100/0ms
          execute time(s)/globals/cmds/disk: 0.0009s/12/1,096/0ms
                                query class: %sqlcq.GBI.cls27, %Library.ProcedureContext
---------------------------------------------------------------------------

Como foi fornecida a aba ( primeira chave ) "A", os dados dos sub-nós são expandidos e retornados como registros.

Os outros nós que não foram selecionados ou não contêm dados são retornados como registros "0".

Conceitos de código

Quando uma consulta ( GetNotes ) é implementada em uma classe, o conteúdo da consulta pode ser obtido apenas com SQL.

Após a compilação, são gerados três class methods:

  • GetNotesExecute
  • GetNotesFetch
  • GetNotesClose

Há vários cenários em que os dados não são SQL:

  • Globais NoSQL
  • Interação parametrizada com um sistema externo para recuperar e consolidar dados

Ao implementar esses três métodos diretamente, é possível controlar o acesso e dar respostas tabulares para uma ampla variedade de recursos de plataforma.

Estas são algumas das variações de interação:

Armazenar em cache todos os dados de resposta antecipadamente

1. O método GetNotesExecute acessaria os recursos para criar uma reposta em um global temporário.

Isso seria útil para uma visão consistente sobre os dados, o que pode envolver o bloqueio do acesso a atualizações por um breve período.

2. O método GetNotesFetch seria chamado repetidamente, retornando registros dos dados temporários

3. The GetNotesClose limparia e excluiria os dados temporários

Dados de respostas dinâmicas

1. O método GetNotesExecute é chamado. Isso não faz muito coisa além de iniciar um contexto qHandle disponível para o método Fetch

2. O método GetNotesFetch é chamado. Sempre que um novo registro é recuperado dinamicamente

3. O método GetNotesClose exige pouca ou nenhuma limpeza

Essa é a abordagem usada no código de exemplo.

Oportunidades de paginação etc.

Dependendo do cenário, o preenchimento dinâmico de lotes de registros de retorno pode ser usado para reduzir a necessidade de executar uma "consulta completa" quando só é necessária uma área da fatia de registros de retorno.

O código

O método execute tem uma expressão $C(0). Isso serve apenas para corresponder a uma string Null, que é diferente de uma string vazia.

Uma string nula pode ser passada quando um procedimento armazenado é invocado com um argumento de string vazio.

O método GetNotesFetch atua como um wrapper objectscript para GetNotesFetchPy, onde ocorre o trabalho de verdade. A lógica é a expectativa de o framework de chamada usar os argumentos ByRef e o wrapper unir isso.

O código é um exemplo de como navegar e recuperar dados NoSQL por código Python.

A implementação em Python usa um bloco try-except para interromper problemas de ambiente de execução do código Python e propagar esses detalhes das informações de erros da maneira normal de volta ao aplicativo do cliente. Isso pode ser ativado ao descomentar a linha que começa com "#x=10/0".

Por exemplo, o erro interrompido retornado ao cliente:

[SQLCODE: <-400>:<Fatal error occurred>]
[%msg: <Python general error 'alwo.PyProcTest::GetNotesFetchPy:Traceback (most recent call last):
                   File "PyProcTest", line 21, in GetNotesFetchPy
                                                                 ZeroDivisionError: division by zero
                    '>]

///Ref: Defining and Using Class Queries
///https://docs.intersystems.com/iris20232/csp/docbook/DocBook.UI.Page.cls?KEY=GOBJ_queries
Classalwo.PyProcTest [ Abstract ]
{
 
///<example>
///do $SYSTEM.SQL.Shell()
///call alwo.PyProcTest_GetNotes('D')
///</example>
QueryGetNotes(tabNameAs%String) As%Query(ROWSPEC = "Tab:%String,NoteId:%Integer,NoteText:%String") [ SqlName = PyProcTest_GetNotes, SqlProc ]
{
}
 
///ObjectScript due to ByRef signature
ClassMethodGetNotesExecute(ByRefqHandleAs%Binary, tabNameAs%String = "") As%Status
{
  setqHandle=##class(alwo.PyNote.GetNotes.qHandle).%New()
  // Note that an empty string passed from SQL statement may appear as the null character $C(0) instead of empty string ""
  set:tabName'=$C(0) qHandle.selectedTab=tabName// may be empty string
  Quit$$$OK
}
 
///ObjectScript due to ByRef signature
ClassMethodGetNotesFetch(ByRefqHandleAs%Binary, ByRefRowAs%List, ByRefAtEndAs%Integer = 0) As%Status [ PlaceAfter = GetNotesExecute ]
{
  setrefRow=##class(alwo.PyNote.GetNotes.Row).%New()
 
  setstatus=..GetNotesFetchPy(.qHandle,.refRow)
  ifqHandle.atEnd {
    setAtEnd=1
  } else {
    // repack output row to $List format
    setRow=$ListBuild(refRow.Tab,+refRow.NoteId,refRow.NoteText)
  }
  Quitstatus
}
 
///Access to tabular view of global 2 keys deep with data at level 2 nodes
///<example>
///zwrite ^alwo.IndexBook
///
///^alwo.IndexBook("A",1)="abc"
///^alwo.IndexBook("A",2)="def"
///^alwo.IndexBook("B")=""
///^alwo.IndexBook("C")=""
///^alwo.IndexBook("D",1)="gef"
///^alwo.IndexBook("E",1)="ijk"
///^alwo.IndexBook("E",2)="lmn"
///<example>
///
///Required output
///<example>
///| Tab | NoteId | NoteText
///--------------------------
///| A   | 1      | abc
///| A   | 2      | def
///| B   | 0      |
///| C   | 0      |
///| D   | 1      | gef
///| E   | 1      | ijk
///| E   | 2      | lmn
///--------------------------
///</example>
ClassMethodGetNotesFetchPy(qHandleAsalwo.PyNote.GetNotes.qHandle, pRowAsalwo.PyNote.GetNotes.Row) As%String [ Language = python ]
{
importiris
importtraceback
ret=iris.cls('%SYSTEM.Status').OK()
try:
  # basedontheexistanceofdefinednodestheniterate
  gname="^alwo.IndexBook"
  gIterator=iris.gref(gname)
  # IterateonKey1"Tab name"whenKey2"NoteId"waspreviouslysettoempty
  if (None==qHandle.currentPage) or (""==qHandle.currentPage):
    qHandle.currentTab=gIterator.order([qHandle.currentTab])
    # changeoftabcontext
    if (None==qHandle.currentTab) or (qHandle.currentTab==""):  # norecords
      qHandle.atEnd=True
      returnret
    # defaultopenfirsttabifhasvalues
    ifqHandle.selectedTab==NoneorqHandle.selectedTab=="":
      qHandle.selectedTab=qHandle.currentTab
  pRow.Tab=qHandle.currentTab
  #x=10/0 # uncommenttodemonstrateZeroDivisionErrorhandling
  # IterateonKey2"NoteId"
  if (qHandle.selectedTab==qHandle.currentTab):
    qHandle.currentPage=gIterator.order([qHandle.currentTab,qHandle.currentPage])
    if (qHandle.currentPage!=None) and (qHandle.currentPage!=""):
      pRow.NoteId=qHandle.currentPage
      pRow.NoteText=gIterator.get([qHandle.currentTab,qHandle.currentPage])
      # checksifcurrentrecordwasthelastone
      next=gIterator.order([qHandle.currentTab,qHandle.currentPage])
      if (None==next) or (""==next):
        qHandle.currentPage=None  # causesiterateonKey1onnextmethodinvocation
exceptException:
 pErrorMessage='alwo.PyProcTest::GetNotesFetchPy:'+(traceback.format_exc())
 returniris.cls('%SYSTEM.Status').Error(2603,pErrorMessage)
returnret
}
 
///ObjectScript due to ByRef signature
ClassMethodGetNotesClose(ByRefqHandleAs%Binary) As%Status
{
  setqHandle=""
  Quit$$$OK
}
 
}

Classe helper qHandle. É inicializada em Execute e atualizada durante a recuperação de registro.

Classalwo.PyNote.GetNotes.qHandleExtends%RegisteredObject
{
 
PropertycurrentTabAs%String;
 
PropertycurrentPageAs%String;
 
PropertyselectedTabAs%String;
 
PropertyatEndAs%Integer [ InitialExpression = 0 ];
 
}

Classe helper para preencher linhas do Python com nomes legíveis:

Classalwo.PyNote.GetNotes.RowExtends%RegisteredObject
{
 
PropertyTabAs%String;
 
PropertyNoteIdAs%String;
 
PropertyNoteTextAs%String;
 
}

Espero que esse exemplo seja útil para explorar algumas novas ideias e possibilidades com o Embedded.

0
0 150
Artigo Danusa Calixto · Nov. 28, 2023 8m read

Olá, Comunidade,
Neste artigo, vou apresentar meu aplicativo iris-mlm-explainer

Esse aplicativo da Web se conecta ao InterSystems Cloud SQL para criar, treinar, validar e prever modelos de ML, fazer previsões e mostrar um painel com todos os modelos treinados e uma explicação sobre o funcionamento de um modelo de machine learning ajustado. O painel fornece plotagens interativas de desempenho do modelo, importância do recurso, contribuições do recurso para previsões individuais, plotagens de dependência parcial, valores SHAP (interação), visualização de árvores de decisões individuais etc.

Pré-requisitos

  • Você precisa ter uma conta no InterSystems Cloud SQL.
  • Você precisa ter o <a book="" en="" getting-started-installing-git="" git-scm.com="" https:="" v2="">Git</a> instalado localmente.
  • Você precisa ter o <a downloads="" https:="" www.python.org="">Python3</a> instalado localmente.  

Primeiros Passos

Vamos seguir as etapas abaixo para criar e visualizar o painel explicativo de um modelo:

  • Etapa 1 : fazer o git pull/clone do repositório

  • Etapa 2 : fazer login no portal de serviços do InterSystems Cloud SQL

    • Etapa 2.1 : adicionar e gerenciar arquivos
    • Etapa 2.2 : importar DDL e arquivos de dados
    • Etapa 2.3 : criar modelo
    • Etapa 2.4 : treinar modelo
    • Etapa 2.5 : validar modelo
  • Etapa 3 : ativar o ambiente virtual do Python

  • Etapa 4 : executar o aplicativo da Web para previsão

  • Etapa 5 : explorar e o painel explicativo

Etapa 1 : fazer o git pull/clone do repositório

Então, vamos começar com a primeira etapa

Crie uma pasta e faça o git pull/clone do repositório em qualquer diretório local

git clone https://github.com/mwaseem75/iris-mlm-explainer.git

 

Etapa 2 : fazer login no portal de serviços do InterSystems Cloud SQL

Faça login no InterSystems Cloud Service Portal
image

 

 

Selecione a implantação executada

image

 

Etapa 2.1 : adicionar e gerenciar arquivos

Clique em "Add and Manage Files" (Adicionar e gerenciar arquivos)

image

O repositório contém os arquivos USA_Housing_tables_DDL.sql(DDL para criar tabelas), USA_Housing_train.csv(dados de treinamento) e USA_Housing_validate.csv(para validação) na pasta de conjuntos de dados. Selecione o botão de upload para adicionar esses arquivos.

Adicionar arquivos

Etapa 2.2 : importar DDL e arquivos de dados

Clique em "Import files" (Importar arquivos), no botão de opção das declarações DDL ou DML e no botão "Next" (Próximo)

Importar DDL

Clique no botão de opção do Intersystems IRIS e em "Next"

IsIRIS

Selecione o arquivo USA_Housing_tables_DDL.sql e pressione o botão para importar arquivos

Importar arquivo DDL

Clique em "Import" na caixa de diálogo de confirmação para criar a tabela

confirmar importação

importação concluída

Clique nas ferramentas da Query em SQL para verificar se as tabelas foram criadas

conferir se as tabelas foram criadas

Importar arquivos de dados

Clique em "Import files" (Importar arquivos), no botão de opção dos dados CSV e no botão "Next" (Próximo)

csv1

Selecione o arquivo USA_Housing_train.csv e clique no botão "Next"

csv2

 

Selecione o arquivo USA_Housing_train.csv na lista suspensa, marque para importar o arquivo como linha de cabeçalho, selecione "Field names in header row match column names in selected table" (Os nomes dos campos na linha de cabeçalho correspondem aos nomes das colunas na tabela selecionada) e clique em "Import files"

csv3

Clique em "Import" na caixa de diálogo de confirmação

csv4

Confira se 4000 linhas foram atualizadas

csv5

Repita as mesmas etapas para importar o arquivo USA_Housing_validate.csv, que contém 1500 registros

csv6

Etapa 2.3 : criar modelo

Clique em "IntegratedML tools" (ferramentas do IntegratedML) e selecione "Create Panel" (Criar painel).

Insira "USAHousingPriceModel" no campo de nome do modelo, selecione a tabela "usa_housing_train" e "Price" no menu suspenso "Field to predict" (Campo para prever). Clique no botão "Create model" para criar o modelo

criar modelo

 

Etapa 2.4 : treinar modelo

Selecione "Train Panel" (Treinar painel), escolha "USAHousingPriceModel" na lista suspensa "Model to train" (Modelo a treinar) e insira "USAHousingPriceModel_t1" no campo de nome do modelo a treinar

TREINAR1

O modelo será treinado após a conclusão do status de execução

TREINAR2

 

Etapa 2.5 : validar modelo

Selecione "Validate Panel" (Validar painel), escolha "USAHousingPriceModel_t1" na lista suspensa "Trained model to validate" (Modelo treinado a validar), selecione "usa_houseing_validate" na lista suspensa "Table to validate model from" (Tabela para validar o modelo) e clique no botão "Validate model" (Validar modelo)

image

Clique em "Show validation metrics" para ver as métricas

mostrar validação

Clique no ícone de gráfico para ver o gráfico "Prediction VS Actual" (Previsão x Real)

gráfico de validação

 

Etapa 3 : ativar o ambiente virtual do Python

O repositório já contém uma pasta de ambiente virtual do python (venv) com as bibliotecas necessárias.

Tudo o que precisamos fazer é ativar o ambiente
No Unix ou MacOS:

$source venv/bin/activate

No Windows:

venv\scripts\activate

###Etapa 4 : definir parâmetros de conexão do InterSystems Cloud SQL

O repositório contém o arquivo config.py. Basta abrir e definir os parâmetros
image
Coloque os mesmos valores usados no InterSystems Cloud SQL
image

 

Etapa 4 : executar o aplicativo da Web para previsão

Execute o comando abaixo no ambiente virtual para iniciar nosso aplicativo principal

python app.py

image

Acesse http://127.0.0.1:5000/ para executar o aplicativo

image

Insira "Age of house" (Idade da casa), "No of rooms" (Nº de cômodos), "No of bedroom" (Nº de quartos) e "Area population" (População da área) para obter a previsão

image

Etapa 5 : explorar e o painel explicativo

Por fim, execute o comando abaixo no ambiente virtual para iniciar nosso aplicativo principal

python expdash.py

imageimage
image

Acesse http://localhost:8050/ para executar o aplicativo
image

O aplicativo listará todos os modelos treinados com nosso "USAHousingPriceModel". Clique no hyperlink "Go to dashboard" (Acessar painel) para visualizar a explicação sobre o modelo

Importância dos recursos. Quais recursos tiveram o maior impacto?
image

Métricas quantitativas para o desempenho do modelo, Qual é a diferença entre o valor previsto e o observado?
image

Previsão e Como cada recurso contribuiu para a previsão?
image

Ajuste os valores dos recursos para mudar a previsão
image

Resumo Shap, Ordenamento dos recursos por valores shap
image

Resumo de interações, Ordenamento dos recursos por valor de interação shap
image

Árvores de decisões, Exibição de árvores de decisões individuais dentro do Random Forest
image

Obrigado

0
0 87
Artigo Danusa Calixto · Nov. 27, 2023 3m read

Com o lançamento do InterSystems IRIS Cloud SQL, estamos recebendo perguntas frequentes sobre como estabelecer conexões seguras por JDBC e outras tecnologias de driver. Temos um ótimo resumo e uma documentação detalhada sobre as tecnologias de driver, mas essa documentação não chega a descrever ferramentas de cliente individuais, como DBeaver, nossa favorita. Neste artigo, vamos descrever as etapas para criar uma conexão segura no DBeaver para sua implantação do Cloud SQL.

Etapa 0: crie sua implantação

Primeiro, faça login no Cloud Services Portal e crie uma implantação do Cloud SQL. Você só precisa se lembrar de marcar a caixa para ativar conexões externas. Tirando isso, todas as configurações padrão devem funcionar bem.

Etapa 1: instale o certificado

Para uma conexão segura, vamos usar certificados para criptografar tudo o que é enviado por ela. Você pode baixar o certificado na página de detalhes da implantação pelo botão "Get X.509 certificate" (Obter certificado X.509):

Em seguida, precisamos armazenar esse certificado em um keystore confiável usando o utilitário keytool. Essa é uma parte padrão da infraestrutura Java, então nada é específico ao IRIS ou ao DBeaver até aqui. Use o comando abaixo para importar o certificado. A localização do arquivo do certificado certificateSQLaaS.pem não importa após executar esse comando, então ele pode ser excluído da pasta de downloads depois. Porém, a localização do arquivo keystore.jks importa. Portanto, execute o comando a partir de uma pasta que faça sentido: onde você continuará a usá-lo para outros fins ou na pasta de instalação do DBeaver, caso seja a única finalidade desse keystore.

keytool -importcert -file path-to-cert/cert-file.pem -keystore keystore.jks

Para mais detalhes, veja a documentação.

Etapa 2: crie um arquivo SSLConfig.properties

Em seguida, precisamos dizer ao driver JDBC do IRIS como encontrar esse keystore, o que é feito através de um arquivo SSLConfig.properties. Esse arquivo de texto simples precisa ser colocado no diretório de trabalho do programa Java que abrirá a conexão JDBC. No Windows, é o %LOCALAPPDATA%\DBeaver, que se traduz em C:\Users\<you>\AppData\Local\DBeaver. No Mac, é geralmente /Applications/DBeaverEE.app/Contents/MacOS. Como alternativa, você também pode criar o arquivo em outro lugar e definir o caminho completo como uma variável de ambiente chamada com.intersystems.SSLConfigFile.

Na sua forma mais simples, esse arquivo só precisa apontar para o keystore e incluir a senha. O caminho do arquivo keystore.jks precisa ter o escape adequado para a leitura pelo Java, então você precisará usar barras invertidas duplas no Windows.

trustStore=/path/to/keystore/keystore.jks
trustStorePassword=keystore-password

Há várias configurações adicionais que você pode definir através desse arquivo descritas na documentação, incluindo configurações do named, mas a indicada acima é suficiente.

Etapa 3: crie sua conexão do DBeaver

Agora que instalamos o certificado e especificamos onde o JDBC do IRIS pode encontrá-lo, podemos criar a conexão do DBeaver. Todas as configurações da guia "Main" no diálogo de criação da conexão podem ser encontradas na tela de detalhes da implementação conforme colada acima:

Só falta dizer para o DBeaver ativar a criptografia definindo o "connection security level" (nível de segurança da conexão) como 10 na guia "Driver properties" (Propriedades do driver):

É isso! Ao clicar em "Test Connection" (Testar conexão), você deve obter um polegar para cima ou uma mensagem de erro útil. No segundo caso, confira esta documentação para solução de problemas se não for óbvio o que deve ser alterado.

Observação para usuários Mac

Se você estiver usando o Mac, parece que há um bug no DBeaver em que o exposto acima pode não ser suficiente. A solução não é convencional, mas funciona. No campo Database/Schema, onde você normalmente colocaria 'USER', insira toda esta string:

USER:sslConnection=true;sslTrustStoreLocation=/pathToTruststore/truststore.jks;sslTrustStorePassword=123456;

Dica e outras sabedorias de @Rick Guidice 
 

0
0 393
Artigo Danusa Calixto · Set. 4, 2023 8m read

Neste tutorial, quero falar sobre consultas de classe. Para ser mais precisa, sobre as consultas baseadas em código escrito pelo usuário:

Muitas pessoas ignoram esse tipo de consulta só porque não estão confortáveis em escrever uma grande quantidade de código ObjectScript para os métodos ou não veem como podem usá-lo nos apps relacionais. No entanto, para ser sincera, para mim — é uma das criações mais legais para o modelo relacional no IRIS! Ele deixa você expor as informações que quiser (não se limita a tabelas do seu banco de dados) como um conjunto de resultados para um cliente. Portanto, você pode basicamente empacotar qualquer dado armazenado no seu banco de dados e além dele em uma "tabela virtual ordenada" que o usuário pode consultar. E, do ponto de vista de um usuário, será o mesmo conjunto de resultados como se ele(a) tivesse consultado uma tabela ou uma visualização.

Como fundamento, aqui estão alguns exemplos do que você pode usar como dados para sua consulta:

  • Indicadores de sistema do IRIS e seu SO local (se o IRIS tiver acesso a eles)
  • Resultados de consultas externas, como REST ou SOAP (por exemplo, se você não quiser enviar solicitações diretamente de um cliente devido à segurança ou por outros motivos)
  • Resultados do cursor incorporado ou da declaração simples
  • Quaisquer dados ad hoc que você mesmo pode compor
  • Praticamente qualquer outra coisa que venha à mente e seja possível obter usando ObjectScript

Vamos ver agora como isso funciona.

Se você estiver usando o Studio – é bastante fácil e simples.

Na sua classe cls, você pode acessar o menu Class – Add – Query:

Na barra de ferramentas "Members", clique no ícone Query:

O New Query Wizard (Assistente de nova consulta) será aberto. Ele guiará você pelas etapas da criação dos métodos necessários para sua consulta funcionar.

Vamos analisar esse processo usando o exemplo mais simples de empacotamento do resultado do cursor incorporado. Aqui, na verdade, vamos escrever uma consulta em uma tabela, mas é apenas para simplificar. Além disso, vamos analisar exemplos do uso de %Query para retornar dados de outras fontes.

Vamos supor que temos uma classe Sample.Human que estende %Persistent e %Populate. Usarei o último para preencher os dados porque sou preguiçosa e porque eu posso:

Class Sample.Human Extends (%Persistent, %Populate)
{

Property Name As %Name;Property DoB As %Date(MAXVAL = 61727, MINVAL = 32507);Property Age As %Integer [ Calculated, SqlComputeCode = {set {Age} = $h - {DoB} \ 365.25}, SqlComputed ];
}

Quando começamos a criar a consulta, o primeiro passo do Wizard é definir um nome e um tipo:

O próximo passo é definir os parâmetros de entrada, se houver algum. Para adicionar um novo parâmetro, clique no botão no topo da coluna de botões à direita:

A próxima etapa é muito importante – você precisa definir nomes e tipos ou colunas em um conjunto de resultados resultante. Ao criar uma consulta baseada em SQL, essa etapa é feita automaticamente pelo sistema – ele só analisa as colunas que você adicionou na consulta e pega os nomes e tipos de dados. A consulta baseada em ObjectScript talvez não tenha nenhum campo, então você precisa informar ao sistema o que esperar.

É isso. Como resultado do Wizard, você terá 3 novos ClassMethods e uma Query na sua classe:

/// Get all the names and ages of people whose age is greater or equal than nput parameter
Query GetAllOlderThan(Age As %Integer = 65) As %Query(ROWSPEC = "Name:%Name,Age:%Integer")
{
}

ClassMethod GetAllOlderThanExecute(ByRef qHandle As %Binary, Age As %Integer = 65) As %Status
{
               Quit $$$OK
}

ClassMethod GetAllOlderThanClose(ByRef qHandle As %Binary) As %Status [ PlaceAfter = GetAllOlderThanExecute ]
{
               Quit $$$OK
}

ClassMethod GetAllOlderThanFetch(ByRef qHandle As %Binary, ByRef Row As %List, ByRef AtEnd As %Integer = 0) As %Status [ PlaceAfter = GetAllOlderThanExecute ]
{
               Quit $$$OK
}

}

A Query só informa ao sistema que existe uma consulta em uma classe que pode ser chamada por um nome com um parâmetro e retornará 2 colunas no resultado. Qualquer código inserido dentro da Query será desconsiderado.

Toda a codificação é feita no ClassMethods. Eles são responsáveis por preencher nosso conjunto de resultados "virtual" ( <QueryName>Execute– chamado quando uma declaração SQL é executada), retornando a próxima linha (<QueryName>Fetch) e deixando tudo organizado (<QueryName>Close. Eles têm um parâmetro em comum – ByRef qHandle As %Binary em que os dados são armazenados e transmitidos entre métodos. Como você pode ver, os dados são binários, então você pode colocar qualquer coisa dentro dele (seguindo seu bom senso). Em  Age As %Integer = 65. And in <QueryName>Fetch there are two additional parameters:

  • ByRef Row As %Listé uma %List que contém a linha atual do conjunto de resultados "virtual" com o número e os valores das colunas descritos na ROWSPEC da Query (Name:%Name, Age:%Integer).
  • ByRef AtEnd As %Integer = 0 – isso é uma sinalização que indica se a linha atual é a última (1) ou não (0).

Se você estiver trabalhando no VSCode, terá que escrever todas as assinaturas por conta própria e tentar não cometer erros😊

Agora que sabemos qual parâmetro é responsável pelo quê, vamos analisar o código:

/// Get all the names and ages of people whose age is greater or equal than nput parameter
Query GetAllOlderThan(Age As %Integer = 65) As %Query(ROWSPEC = "Name:%Name,Age:%Integer") [ SqlProc ]
{
}

ClassMethod GetAllOlderThanExecute(ByRef qHandle As %Binary, Age As %Integer = 65) As %Status
{
     &sql(DECLARE C CURSOR FOR
        SELECT Name, Age
          FROM Sample.Human 
         WHERE Age >= :Age
     )
     &sql(OPEN C)
    Quit $$$OK
}

ClassMethod GetAllOlderThanClose(ByRef qHandle As %Binary) As %Status [ PlaceAfter = GetAllOlderThanExecute ]
{
    &sql(CLOSE C)
    Quit $$$OK
}

ClassMethod GetAllOlderThanFetch(ByRef qHandle As %Binary, ByRef Row As %List, ByRef AtEnd As %Integer = 0) As %Status [ PlaceAfter = GetAllOlderThanExecute ]
{
    &sql(FETCH C INTO :Name, :Age)
    If (SQLCODE'=0) {
        Set AtEnd = 1
        Set Row = ""
        Quit $$$OK
    }
    Set Row = $Lb(Name, Age)
    Quit $$$OK
}

Esse código declara e abre um cursor incorporado que seleciona os nomes e as idades das pessoas com mais de Age em <QueryName>Execute, busca o resultado do cursor, forma uma lista em <QueryName>Fetch e depois a fecha em &;lt;QueryName>Close.

Podemos chamá-lo usando código:

SET tStatement = ##class(%SQL.Statement).%New()
 SET rstatus = tStatement.%PrepareClassQuery("Sample.Human","GetAllOlderThan")
 SET rset = tStatement.%Execute()
 DO rset.%Display()

Muito bom e simples. E provavelmente não é o que você estava procurando.

Como exemplo do uso sem dados armazenados no banco de dados, digamos que por algum motivo não temos acesso às tabelas reais, mas precisamos conferir se nosso aplicativo funciona como esperado. Precisamos que a consulta retorne alguns dados de teste. Podemos reescrever esse exemplo para que os dados sejam gerados automaticamente durante a busca de uma nova linha.

Obviamente, não precisamos salvar os dados na memória, então não há necessidade de preencher a variável qHandle em <QueryName>Execute – podemos criar os dados dentro de <QueryName>Fetch. E, em qHandle vamos armazenar o tamanho do conjunto de resultados a ser retornado (um número aleatório menor que 200, por exemplo) e o número da linha atual que vamos incrementar em <QueryName>Fetch. No final, vamos obter este código:

Query GetAllOlderThan(Age As%Integer = 65) As%Query(ROWSPEC = "Name:%Name,Age:%Integer") [ SqlProc ]
{
}

ClassMethod GetAllOlderThanExecute(ByRef qHandle As%Binary, Age As%Integer = 65) As%Status
{
    set qHandle = $lb($random(200), 0, Age)
    Quit$$$OK
}

ClassMethod GetAllOlderThanClose(ByRef qHandle As%Binary) As%Status [ PlaceAfter = GetAllOlderThanExecute ]
{
    set qHandle = ""Quit$$$OK
}

ClassMethod GetAllOlderThanFetch(ByRef qHandle As%Binary, ByRef Row As%List, ByRef AtEnd As%Integer = 0) As%Status [ PlaceAfter = GetAllOlderThanExecute ]
{
	if$ListGet(qHandle, 2) = $ListGet(qHandle, 1)
	{
		Set Row = ""set AtEnd = 1
	} else
	{
    	Set Row = $Lb(##class(%PopulateUtils).Name(), ##class(%PopulateUtils).Integer($ListGet(qHandle, 3), 90))
    	set$list(qHandle, 2) = $list(qHandle, 2) + 1
	}
    Quit$$$OK
}

}

Como você pode ver, estou gerando dados ad hoc. Isso significa que você pode obter seus dados de qualquer lugar, empacotar em um conjunto de resultados e torná-lo acessível pelo app que usa ODBC/JDBC fora do banco de dados IRIS. O que, por sua vez, significa que você pode usar o acesso relacional habitual para obter dados não relacionais se você conseguir estruturá-lo.

0
0 86
Artigo Danusa Calixto · Ago. 8, 2023 4m read

Com o InterSystems IRIS 2022.2, apresentamos o armazenamento colunar como uma nova opção para a persistência das suas tabelas SQL do IRIS que pode otimizar suas consultas analíticas por ordem de magnitude. O recurso está marcado como experimental em 2022.2 e 2022.3, mas se tornará um recurso de produção totalmente compatível no próximo lançamento de 2023.1. 

A documentação do produto e este vídeo introdutório já descrevem as diferenças entre o armazenamento em linhas, que ainda é o padrão no IRIS e é usado pela nossa base de clientes, e o armazenamento de tabela colunar, além de fornecer orientações de alta qualidade para a escolha do layout de armazenamento adequado para seu caso de uso. Neste artigo, vamos falar sobre esse tema e compartilhar algumas recomendações com base nos princípios de modelagem do setor, testes internos e feedback dos participantes do Programa de Acesso Antecipado. 

Em geral, nossas orientações para escolher um layout de tabela adequado para seu esquema SQL do IRIS são as seguintes:

  1. Se você estiver implantando um aplicativo que usa o SQL ou Objects do IRIS, como um aplicativo de EHR, ERP ou processamento de transações, não é necessário mudar o armazenamento em linhas atual para o layout colunar. A maioria das consultas SQL emitidas para aplicativos ou transações programáticas de usuários finais só recuperam ou atualizam um número limitado de linhas, e as linhas de resultado geralmente correspondem às linhas da tabela, com uso bastante limitado das funções de agregação. Nesses casos, os benefícios oferecidos pelo armazenamento colunar e o processamento de consultas vetorizado não se aplicam.  
  2. Se esse aplicativo também incorpora a análise operacional, considere adicionar índices colunares se o desempenho atual das consultas analíticas correspondentes não for satisfatório. Isso inclui, por exemplo, painéis que mostram o inventário atual ou relatórios financeiros básicos com dados em tempo real. Procure campos numéricos em agregações (por exemplo, quantidades e moedas) ou campos de cardinalidade alta usados em condições de intervalos (por exemplo, carimbos de data/hora). Um bom indicador dessas oportunidades é o uso atual de índices de bitmap para acelerar a filtragem de grandes números de linhas, geralmente em campos de cardinalidade baixa (por exemplo, campos categóricos ou ordinais). Não é necessário substituir esses índices de bitmap. Os índices colunares adicionais funcionam bem em conjunto com eles e são criados para evitar leituras excessivas do mapa principal ou dos mapas de índice normais (um único gref por linha).  
  3. Se suas tabelas SQL do IRIS tiverem menos de um milhão de linhas, não é preciso considerar o armazenamento colunar. Preferimos não nos ater a números específicos, mas os benefícios do processamento de consultas vetorizado provavelmente não farão diferença nesses níveis mais baixos.  
  4. Se você estiver implantando um esquema SQL do IRIS para armazém de dados, inteligência de negócios ou casos de uso analíticos semelhantes, considere mudar para o armazenamento colunar como padrão. Os esquemas em estrela, floco de neve ou outras estruturas de tabela desnormalizadas, além da ampla utilização de índices de bitmap e ingestão em lote, são bons indícios para esses casos de uso. As consultas analíticas que mais se beneficiam do armazenamento colunar são aquelas que verificam grandes números de linhas e valores agregados. Ao definir uma "tabela colunar”" o IRIS recorrerá com transparência a um layout de linhas para as colunas dessa tabela que não são adequadas para o armazenamento colunar, como fluxos, strings longas ou campos seriais. O SQL do IRIS é totalmente compatível com esses layouts de tabela mistos e usará o processamento de consultas vetorizado para as partes qualificadas do plano de consulta. O valor agregado dos índices de bitmap nas tabelas colunares é limitado, então ele pode ser deixado de fora.

O proveito variará com base nos parâmetros ambientais e relacionados a dados. Portanto, recomendamos enfaticamente que os clientes testem os diferentes layouts em uma configuração representativa. Os índices colunares são fáceis de adicionar a uma tabela regular organizada por linhas e fornecerão rapidamente uma perspectiva realista dos benefícios do desempenho da consulta. Isso, com a flexibilidade de layouts de tabela mistos, é um diferencial importante do InterSystems IRIS que ajuda os clientes a obter uma melhoria de desempenho de ordem de magnitude.

Pretendemos tornar essas recomendações mais concretas conforme tivermos mais experiência real com a versão de produção completa. Obviamente, podemos fornecer conselhos mais concretos com base no esquema real e na carga de trabalho dos clientes pelo Programa de Acesso Antecipado e compromissos com POCs, e aguardamos o feedback de clientes e membros da comunidade. O armazenamento colunar faz parte da licença do InterSystems IRIS Advanced Server e também está habilitado na Community Edition do InterSystems IRIS e IRIS for Health. Para um ambiente de demonstração com script completo, consulte este repositório do GitHub.

0
0 77
Artigo Cristiano Silva · Maio 5, 2023 2m read

Apache Superset é uma plataforma moderna de exploração e visualização de dados. O Superset pode substituir ou trazer ganhos para as ferramentas proprietárias de business intelligence para muitas equipes. O Superset integra-se bem com uma variedade de fontes de dados.

E agora é possível usar também com o InterSystems IRIS.

Uma demo online está disponível e usa IRIS Cloud SQL como sua fonte de dados.

0
0 427
Artigo Danusa Calixto · Abr. 4, 2023 2m read

Olá desenvolvedores!

Como você sabe, o IRIS da InterSystems além de globais, objetos, documentos e modelos de dados XML também suporta relacional onde o SQL é esperado como uma linguagem para lidar com os dados.

E como em outros DBMS relacionais, o InterSystems IRIS possui seu próprio dialeto.

Começo esta postagem para dar suporte a uma folha de dicas SQL e convido você a compartilhar seus favoritos - atualizarei o conteúdo com os comentários recebidos.

Aqui vamos nós!

0
0 69
Artigo Heloisa Paiva · Mar. 10, 2023 3m read

Introdução

Esse artigo tem a intenção de ser um simples tutorial sobre como criar conexões ODBC e trabalhar com elas, já que eu achei o assunto um pouco confuso quando estava começando, mas tive pessoas incríveis que pegaram minha mão e me guiaram para conseguir, e eu acredito que todos merecem esse tipo de ajuda também.

Vou dividir cada pequena parte em seções, então sinta-se à vontade para pular para a que sentir necessidade, apesar de eu recomendar ler o texto na íntegra.

0
0 439
Artigo Heloisa Paiva · Mar. 9, 2023 3m read

Introdução

Em alguns dos últimos artigos, eu falei sobre tipos entre IRIS e Python, e ficou claro que não é tão fácil acessar objetos de um lado pelo outro.

Por sorte, o trabalho já foi feito para criar o SQLAlchemy-iris (clique no link para ver na Open Exchange), o que faz tudo muito mais fácil para o Python acessar os objetos do IRIS, e eu vou mostrar como começar.

Obrigada @Dmitry Maslennikov !

Instalando

Para instalar, simplesmente abra seu terminal com acesso do administrador e digite

pip install sqlalchemy-iris

 

Isso também vai instalar os pré-requisitos, se necessário.

Usando

2
0 1199
Artigo Heloisa Paiva · Mar. 2, 2023 3m read

 Introdução

Esse é um tutorial simples da forma mais rápida que eu achei para criar uma base de dados de exemplo para quaisquer razões, como realizar testes, fazer exemplos para tutoriais, etc.

Criando um namespace

  1. Abra o terminal
  2. Escreva o comando "D $SYSTEM.SQL.Shell()"
  3. Escreva"CREATE DATABASE " e o nome desejado para o namespace.

Agora você tem um namespace novo de uma forma muito mais rápida que criando pelo Portal de Administração - que é claro que oferece muito mais opções de configuração.

0
0 146
Artigo Danusa Calixto · jan 11, 2023 5m read

Como você deve se lembrar do Global Summit 2022 ou do 2022.2 launch webinar, estamos lançando um novo e empolgante recurso para incluir em suas soluções analíticas no InterSystems IRIS. O Armazenamento Colunar apresenta uma maneira alternativa de armazenar os dados da tabela SQL que oferece uma aceleração de ordem de grandeza para consultas analíticas. Lançado pela primeira vez como um recurso experimental em 2022.2, o mais recente Developer Preview 2022.3 inclui várias atualizações que achamos que valeriam uma postagem rápida aqui.

0
0 57
Artigo Danusa Calixto · Out. 10, 2022 8m read

No vasto e variado mercado de banco de dados SQL, o InterSystems IRIS se destaca como uma plataforma que vai muito além do SQL, oferecendo uma experiência multimodelo otimizada e a compatibilidade com um rico conjunto de paradigmas de desenvolvimento. Em especial, o mecanismo Object-Relational avançado ajudou as organizações a usar a abordagem de desenvolvimento mais adequada para cada faceta das cargas de trabalho com muitos dados, por exemplo, fazendo a ingestão de dados por objetos e consultando-os simultaneamente por SQL. As Classes Persistentes correspondem às tabelas SQL, suas propriedades às colunas da tabela, e a lógica de negócios é facilmente acessada usando as Funções Definidas pelo Usuário ou os Procedimentos Armazenados. Neste artigo, focaremos um pouco na mágica logo abaixo da superfície e discutiremos como isso pode afetar suas práticas de desenvolvimento e implantação. Essa é uma área do produto em que temos planos de evoluir e melhorar, portanto, não hesite em compartilhar suas opiniões e experiências usando a seção de comentários abaixo.

Salvando a definição de armazenamento

Escrever uma nova lógica de negócios é fácil e, supondo que você tenha APIs e especificações bem definidas, adaptá-la ou ampliá-la também costuma ser. No entanto, quando não é apenas lógica de negócios, mas também envolve dados persistentes, qualquer coisa que você alterar na versão inicial precisará ser capaz de lidar com os dados que foram ingeridos por essa versão anterior.

No InterSystems IRIS, os dados e código coexistem em um único mecanismo de alto desempenho, sem a meia dúzia de camadas de abstração que você vê em outras estruturas de programação 3GL ou 4GL. Isso significa que há apenas um mapeamento muito fino e transparente para traduzir as propriedades da sua classe para posições $list em um nó global por linha de dados ao usar o armazenamento padrão. Se você adicionar ou remover propriedades, não quer que os dados de uma propriedade removida apareçam em uma nova propriedade. É desse mapeamento das propriedades da sua classe que a Definição de Armazenamento cuida, um bloco de XML um pouco enigmático que você deve ter percebido na parte inferior da definição da sua classe. Na primeira vez que você compila uma classe, uma nova Definição de Armazenamento é gerada com base nas propriedades e nos parâmetros da classe. Quando você faz alterações na definição da classe, no momento da recompilação, essas alterações são reconciliadas com a Definição de Armazenamento existente e alteradas para manter a compatibilidade com os dados existentes. Assim, enquanto você se esforça para refatorar as classes, a Definição de Armazenamento considera cuidadosamente sua criatividade anterior e garante que os dados antigos e novos permaneçam acessíveis. Chamamos isso de evolução de esquema.

Na maioria dos outros bancos de dados SQL, o armazenamento físico das tabelas é muito mais opaco, se visível, e as alterações só podem ser feitas por declarações ALTER TABLE. Esses são comandos de DDL (linguagem de definição de dados) padrão, mas normalmente são muito menos expressivos do que é possível alcançar ao modificar uma definição de classe e um código de procedimento diretamente no IRIS. 

Na InterSystems, nos esforçamos para oferecer aos desenvolvedores do IRIS a capacidade de separar de forma limpa o código e os dados, pois isso é crucial para garantir o empacotamento e a implantação suave dos aplicativos. A Definição de Armazenamento desempenha uma função única nisso, pois captura como um mapeia para o outro. Por isso, vale a pena examinar mais a fundo o contexto de práticas gerais de desenvolvimento e pipelines de CI/CD em particular.

Exportando para UDL

No século atual, o gerenciamento de código-fonte é baseado em arquivos, então vamos primeiro analisar o formato principal de exportação de arquivos do IRIS. A Linguagem de Descrição Universal (Universal Description Language ou UDL, na sigla em inglês) pretende, como o nome sugere, ser um formato de arquivo universal para todo e qualquer código que você escrever no InterSystems IRIS. É o formato de exportação padrão ao trabalhar com o plug-in VS Code ObjectScript e leva a arquivos fáceis de ler que parecem quase iguais ao que você veria em um IDE, com um arquivo .cls individual para cada classe (tabela) no seu aplicativo. Você pode usar $SYSTEM.OBJ.Export() para criar arquivos UDL explicitamente ou apenas aproveitar a integração do VS Code.

Da época do Studio, talvez você se lembre de um formato XML que capturava as mesmas informações do UDL e permitia agrupar várias classes em uma única exportação. Embora essa última parte seja conveniente em alguns cenários, é muito menos prático ler e rastrear diferenças entre versões, então vamos ignorá-la por enquanto.

Como a UDL é destinada a capturar tudo o que o IRIS pode expressar sobre uma classe, ela incluirá todos os elementos de uma definição de classe, incluindo a Definição de Armazenamento completa. Ao importar uma definição de classe que já inclui uma Definição de Armazenamento, o IRIS verificará se essa Definição de Armazenamento abrange todas as propriedades e índices da classe e, se for o caso, usará no estado em que está e substituirá a Definição anterior para essa classe. Isso torna a UDL um formato prático para o gerenciamento de versões das classes e a Definição de Armazenamento, pois preserva essa compatibilidade para dados ingeridos por versões anteriores da classe, onde quer que você implante. 

Se você é um desenvolvedor hardcore, talvez se pergunte se essas Definições de Armazenamento continuam crescendo e se essa "bagagem" precisa ser transportada indefinidamente. O objetivo das Definições de Armazenamento é preservar a compatibilidade com dados pré-existentes, portanto, se você sabe que não há nada disso e quiser se livrar de uma genealogia longa, pode "redefinir" a Definição de Armazenamento ao removê-la da definição da classe e gerar outra com o compilador da classe. Por exemplo, você pode usar isso para aproveitar novas práticas recomendadas, como o uso de Conjuntos de Extensão, que implementam nomes globais com hash e separam cada índice em um próprio global, melhorando as eficiências de baixo nível. Para a compatibilidade com versões anteriores nos aplicativos dos clientes, não podemos mudar universalmente esses padrões na superclasse %Persistent (embora os aplicaremos ao criar uma tabela do zero usando o comando DDL CREATE TABLE). Portanto, uma revisão periódica das classes e do armazenamento vale a pena. Também é possível editar o XML de Definição de Armazenamento diretamente, mas os usuários precisam ter muito cuidado, pois isso pode tornar os dados existentes inacessíveis.

Até aqui, tudo bem. As Definições de Armazenamento oferecem um mapeamento inteligente entre suas classes e se adaptam automaticamente com a evolução do esquema. O que mais tem lá?

Estático x Estatísticas?

Como você provavelmente sabe, o mecanismo SQL do InterSystems IRIS faz o uso avançado de estatísticas de tabela para identificar o plano de consulta ideal para qualquer declaração executada pelo usuário. As estatísticas de tabela incluem métricas sobre o tamanho de uma tabela, como os valores são distribuídos em uma coluna e muito mais. Essas informações ajudam o otimizador de SQL do IRIS a decidir qual índice é mais vantajoso, em que ordem unir as tabelas, etc. Portanto, intuitivamente, quanto mais atualizadas as estatísticas estiverem, maiores serão as chances de planos de consulta ideais. Infelizmente, até a introdução da amostragem de bloco rápida no IRIS 2021.2, coletar estatísticas de tabela precisas costumava ser uma operação computacionalmente cara. Portanto, quando os clientes implantavam o mesmo aplicativo em vários ambientes com padrões de dados basicamente iguais, fazia sentido considerar as estatísticas de tabela como parte do código do aplicativo e incluí-las nas definições da tabela.

Por isso, no IRIS hoje você encontra as estatísticas de tabela incorporadas à Definição de Armazenamento. Ao coletar estatísticas de tabela por uma chamada manual para TUNE TABLE ou de maneira implícita pela consulta (veja abaixo), as novas estatísticas são gravadas na Definição de Armazenamento e os planos de consulta existentes para essa tabela são invalidados, para que possam aproveitar as novas estatísticas durante a próxima execução. Por serem parte da Definição de Armazenamento, essas estatísticas farão parte das exportações de classe UDL e, portanto, podem acabar no seu repositório de código-fonte. No caso de estatísticas cuidadosamente verificadas para um aplicativo empacotado, isso é desejado, pois você quer que essas estatísticas específicas levem à geração do plano de consulta para todas as implantações do aplicativo.

A partir de 2021.2, o IRIS coletará automaticamente as estatísticas de tabela no início do planejamento de consulta ao consultar uma tabela que não possui nenhuma estatística e está qualificada para a amostragem de bloco rápida. Nos nossos testes, os benefícios de trabalhar com estatísticas atualizadas em vez de nenhuma estatística superaram claramente o custo da coleta de estatísticas em tempo real. Para alguns clientes, no entanto, isso teve o lamentável efeito colateral das estatísticas coletadas automaticamente na instância do desenvolvedor terminarem na Definição de Armazenamento no sistema de controle de fonte e, por fim, no aplicativo empacotado. Obviamente, os dados nesse ambiente de desenvolvedor e, portanto, as estatísticas nele talvez não sejam representativos para uma implantação real do cliente e levem a planos de consulta abaixo do ideal.

É fácil evitar essa situação. As estatísticas de tabela podem ser excluídas da exportação da definição de classe usando o qualificador /exportselectivity=0 ao chamar $SYSTEM.OBJ.Export(). O padrão do sistema para essa sinalização pode ser configurado usando $SYSTEM.OBJ.SetQualifiers("/exportselectivity=0"). Depois, deixe para a coleta automática na eventual implantação coletar estatísticas representativas, tornar a coleta de estatísticas explícitas parte do processo de implantação, o que substituirá qualquer coisa que possa ter sido empacotada com o aplicativo, ou gerenciar suas estatísticas de tabela separadamente pelas próprias funções de importação/exportação: $SYSTEM.SQL.Stats.Table.Export() e Import().  

A longo prazo, pretendemos mover as estatísticas de tabela para ficar com os dados, em vez de fazer parte do código, e diferenciar mais claramente entre quaisquer estatísticas configuradas explicitamente por um desenvolvedor e as coletadas de dados reais. Além disso, estamos planejando mais automação em relação à atualização periódica dessas estatísticas, com base em quanto os dados da tabela mudam ao longo do tempo. 

Conclusão

Neste artigo, descrevemos a função de uma Definição de Armazenamento no mecanismo ObjectRelational do IRIS, como ela é compatível com a evolução do esquema e o que significa incluí-la no seu sistema de controle de fonte. Também descrevemos por que as estatísticas de tabela são atualmente armazenadas nessa Definição de Armazenamento e sugerimos práticas de desenvolvimento para garantir que as implantações de aplicativos acabem com estatísticas representativas dos dados reais do cliente. Conforme mencionado anteriormente, planejamos aprimorar ainda mais esses recursos. Portanto, aguardamos seu feedback sobre a funcionalidade atual e planejada para refinar nosso design conforme apropriado.

0
0 88
Pergunta Anderson F · Abr. 5, 2022

Bom dia a todos.

Preciso consultar informações das tabelas/classes que estejam em lock

Eu achei na documentação a classe %SYS.LockQuery mas no exemplo ela parece ser uma Class Query(não estou acostumado com esse conceito) e só consigo consumir os dados via Object Script usando um %ResultSet

Existe alguma forma de consumir essas informações diretamente via SQL ?

Grato por qualquer ajuda

2
0 296
Pergunta Renato Araujo · Mar. 8, 2022

Boa tarde à todos!

Preciso fazer uma chamada sql (utilizando JDBC) para executar uma procedure que retorna um objeto estruturado (Oracle Object) como parâmetro de saída.

No entanto, o método do Adptador SQL não está aceitando o tipo de dado STRUCT do JDBC (referente ao Oracle Oject), retornando a seguinte mensagem de erro:

ERRO #5023: Erro no Gateway Remoto: JDBC Gateway SP execute(0) error 0: Remote JDBC error: ORA-06550: line 1, column 7:
PLS-00306: wrong number or types of arguments in call to 'AGUARDAR_EVENTO'
ORA-06550: line 1, column 7:
PL/SQL: Statement ignored

1
0 248
Artigo Rochael Ribeiro · Fev. 21, 2022 2m read

Olá desenvolvedores!

Algumas vezes precisamos inserir ou fazer referência aos dados de classes persistentes diretamente através das globais.

E talvez muitos de vocês estejam esperando que a estrutura de dados da global com os registros seja:

^Sample.Person(Id)=$listbuild("",col1,col,2,...,coln).

Este artigo é um aviso que nem sempre isso é verdade. Não espere que sempre seja assim!

0
0 86
Artigo Rochael Ribeiro · Fev. 21, 2022 2m read

Olá Desenvolvedores!

Como você provavelmente percebeu, no IRIS 2021 os nomes das globais são randômicos.

E, se você criar classes do IRIS classes com DDL e quiser se certificar qual global foi criada, você provavelmente gostaria de escolher seu nome.

E, de fato, você consegue fazê-lo. 

Utilize WITH %CLASSPARAMETER DEFAULTGLOBAL='^GLobalName' na instrução CREATE Table para fazê-lo. Documentação. Veja o exemplo abaixo:

0
0 75
Artigo Gabriel Schiehl · Jul. 7, 2021 1m read

Recentemente, eu queria obter uma lista de todas as consultas em cache e seus textos. Veja como fazer isso.
Primeiro, crie um procedimento SQL retornando texto de consulta de cache a partir de um nome de rotina de consulta em cache:

Class test.CQ
{

/// SELECT test.CQ_GetText()
ClassMethod GetText(routine As %String) As %String [ CodeMode = expression, SqlProc ]
{
##class(%SQLCatalog).GetCachedQueryInfo(routine)
}

}
E depois disso, você pode executar esta consulta:
SELECT Routine, test.CQ_GetText(Routine)
FROM %SQL_Manager.CachedQueryTree()
E obtenha uma lista de consultas em cache:
0
0 222
Artigo ROBSON SERPA DA ROSA · Jun. 28, 2021 5m read

Uma VIEW em SQL é basicamente uma instrução SQL preparada.
Deve ser executado e montado como qualquer outra consulta SQL.
VIEW MATERIALIZADA significa que o conteúdo é coletado antes das mãos e pode ser recuperado com bastante rapidez.
Eu vi o conceito primeiro com meu concorrente favorito chamado O * e eles fizeram muito barulho sobre isso.

  { favorite: because I could win every benchmark against them devil }

0
0 117
Artigo Jhonata Rebouças · Maio 1, 2021 5m read

O mesmo serviço com a possibilidade de receber várias consultas SQL diferentes e sempre entregar o resultado independente de quantas colunas distintas tenham essas diferentes consultas. Aqui demonstro como pode ser possível montar esse tipo de serviço utilizando o Service Bus da Intersystems.

Possível cenário (Desconsiderar o uso de um BI):

Vamos pensar em um painel real time onde iremos fornecer as informações de consumo de um material por região para o setor de compras e teremos as informações do nome do produto, fabricante e quantidade por exemplo.

0
1 258