Nueva publicación

Encontrar

Pregunta
· 29 mayo, 2024

Is there a way to do an override of a %ALL Global Mapping?

Let's say I have an InterSystems IRIS instance with 6 Namespaces:

  • Foo1
  • Foo2
  • Foo3
  • Foo4
  • Foo5
  • Bar

And the number of Foo# namespaces can increase at any time for a number of reasons.  I need to ensure that they all have identical configuration globals stored in a DB called CONFIG, so I do the following in my configuration file:

[Map.%ALL] 
Global_SYS=%DEFAULTDB 
Global_SYS("CommonConfig")=CONFIG 
Global_SYS("CommonOtherSettings")=CONFIG 
Global_SourceControl=CONFIG 

This will ensure that all Namespace see the exact same settings when they reference ^SYS("CommonConfig") or ^SourceControl, etc.

Now...

... say that I need the "Bar" namespace to have unique ^SYS("CommonConfig")  values and so I need to explicitly map it to a BARCONFIG database.  Is there a way I can do this while maintaining my exiting %ALLl mappings?  Please note that this isn't hypothetical, and the existing %ALL mappings are already deployed production configurations, so reworking those is not an option.  I just need to figure out if there is an out of the box way to have my Bar namespace see different versions of these globals, or if I am going to have to write special logic to have Bar know it needs to look somewhere other than the standard configuration for its globals (which I really want to avoid since there are many, many places relying on these global locations)

Any advice and/or help would be most appreciated!! 

9 comentarios
Comentarios (9)3
Inicie sesión o regístrese para continuar
Pregunta
· 29 mayo, 2024

Como comunicar mediante la interoperabilidad con un Industrial Gateway OPC Server

Tengo un sistema Scada iFIX que soporta VBA comunicando con IRIS mediante sockets. En el entorno VBA del iFIX empleo el control MSWINSCK.OCX que funciona perfectamente con la versión antigua del iFIX. Al querer pasar a la nueva versión de iFIX este control ya no me funciona, es por eso que quiero intentar solucionar el problema comunicando directamente con el OPC que está debajo del iFIX. La idea es mandarle un bit 1 desde IRIS cuando actualizo unos datos, el OPC debería recibirlo en un TAG y el iFIX podría leer del OPC ese bit.

No sé si lo conseguiré, veo que el OPC server comunica con gran cantidad de dispositivos...

¿Alguien lo ha hecho alguna vez?

Gracias por adelantado

2 comentarios
Comentarios (2)2
Inicie sesión o regístrese para continuar
Artículo
· 29 mayo, 2024 Lectura de 3 min

Uso de VECTORES en ObjectScript

La mayoría de los ejemplos que he visto hasta ahora en OEX o DC dejan la impresión de que los VECTORES son sólo algo disponible con SQL con las 3 Funciones especialmente alrededor de VECTOR_Search.
* TO_VECTOR()
* VECTOR_DOT_PRODUCT ()
* VECTOR_COSINE ()

Hay un resumen muy útil escondido en el paquete de demostración iris-vector-search.
Desde allí encontraréis todo lo que necesitáis en varios enlaces y rincones.

Me faltaban más métodos VECTOR y añadí una solicitud al respecto en el Portal de Ideas.
 
Luego recordé que cada método o procedimiento SQL se basa en un montón de código ObjectScript.
Así que fui a buscarlo y este es el resumen de la investigación.

%Library.Vector es la descripción básica del nuevo DataType (tipo de datos).
Es una estructura compleja como Objects o %DynamicObjects o $Bit Expressions que requieren métodos de acceso específicos.
También vemos 2 parámetros requeridos: 

* DATATTYPE  - una vez configurado no se puede cambiar.
 Tipos aceptados:  "integer" (o "int"), "double", "decimal", "string" y "timestamp".
* LEN >0 , puede crecer pero nunca reducirse.

$vector() / &ve() es el método básico para el acceso al Vector.
Asignar Datos Vectoriales  >>>  SET $VE(. . .) = val
Devolver Datos Vectoriales  >>>  WRITE $VE(. . .) ,  SET var=$VE(. . .) 
  ¡SUGERENCIA: una sola posición devuelve el valor, pero la posición from::to devuelve otro Vector!
Eliminar Datos Vectoriales >>>  KILL $VE(. . .) 

Los 3 requieren al menos 1 parámetro de Posición. Podéis entender esto como dimensiones.

$isvector() la verificación obvia del formato correcto antes de comenzar las operaciones.

$vectorop() / $vop() cubre todas las demás funciones relacionadas con los vectores.
Los parámetros de llamada suelen ser (operación, vector)
Algunas operaciones ofrecen opcionalmente un bitexpr. Marca posiciones/dimensiones a excluir/incluir.
Ejemplo:
- Pensad en un vector 3D. Solo se desea operar en los ejes x e y, no en z.

Operaciones de un solo vector

Operaciones Agregadas
 * "count"
 * "max"
 * "min"
 * "sum"
Operaciones de filtrado
 * "defined"
 * "undefined"
 * "<"
 * "<="
 * ">"
 * ">="
 * "="
 * "!="
 * "between"
Operaciones Numéricas
 * "+"
 * "-"
 * "/"
 * "*"
 * "**"
 * "#"
 * "e-"
 * "e/"
 * "ceiling"
 * "floor"
Operaciones de String
 * "_"
 * "e_"
 * "lower"
 * "upper"
 * "substring"
 * "trim"
 * "triml"
 * "trimr"
Operaciones de Agrupación
 * "group"
 * "countgb"
Operaciones Diversas
 * "convert"
 * "length"
 * "mask"
 * "positions"
 * "set"
Operaciones Informativas
 * "bytesize"
 * "type"

Operaciones multivectoriales (normalmente 2 vectores)

Operaciones de Filtrado Vectorial
 * "v<"
 * "v<="
 * "v>"
 * "v>="
 * "v="
 * "v!="
Operaciones Aritméticas Vectoriales
 * "v+"
 * "v-"
 * "v/"
 * "v*"
 * "v**"
 * "v#"
Concatenación de vectores
 * "v_"
Agrupación de Vectores
 * "countg"
 * "maxg"
 * "ming"
 * "sumg"
Fusión de Vectores
 * "vset"

Ya veis que hay un rico conjunto de herramientas disponibles. Si se estudian los documentos en detalle, el propósito o la ventaja de los resultados puede que no sean evidentes de inmediato. No obstante, espero que os hayáis hecho una idea general de lo que hay disponible ahora.

Comentarios (0)1
Inicie sesión o regístrese para continuar
Artículo
· 29 mayo, 2024 Lectura de 7 min

Optimización de consultas SQL en IRIS

¡Hola a todos los estimados miembros de la comunidad de desarrolladores de InterSystems en español!

Aunque suelo consultar la comunidad de desarrolladores y alguna vez he dejado alguna pregunta por aquí, este será mi primer artículo y qué mejor ocasión para hacerlo que participando en el 3er concurso de artículos técnicos.

El tema que trataré en este artículo será el de las diferentes herramientas que nos proporciona InterSystems IRIS para optimizar tanto las bases de datos como las consultas que ejecutamos así como los nuevos tipos de almacenamiento y de datos.

 

Optimizando nuestras consultas SQL

Para este artículo he montado en una instancia de InterSystems IRIS Community un pequeño ejemplo importando un CSV con 5 millones de registros de hipotéticas ventas realizadas a lo largo de los años en diferentes ciudades.

La estructura de las tablas será muy sencilla, pero suficiente para realizar las pruebas que necesitamos, disculpad los nombres, pero ya sabéis que no hay nada más permanente que una solución temporal:

Sales.Record

SumaVentasMensuales CodigoCiudad Anyo Mes
454323 1 1995 3
... ... ... ...

Concurso.Localidad

CodigoCiudad Ciudad CodigoComunidad Comunidad
1 Valladolid 1 Castilla y León
... ...    

Vamos a intentar extraer cual es la media histórica de las ventas de una ciudad como Valladolid en un año determinado:

Vamos a ver lo que tarda nuestra consulta en devolvernos la media de ventas mensuales:

El resultado ha sido un poco más de 8 segundos en retornar el valor medio de las ventas mensuales Si veis disponemos de una opción que nos permitirá conocer el plan de ejecución de la consulta (Mostrar plan). Veamos paso a paso que va a hacer nuestra consulta:

Veamos el módulo H que tiene una información bastante intesante:

• Divide master map Concurso.Localidad(L).IDKEY into subranges of IDs.

• Call module A in parallel on each subrange, piping results into temp-file D.
 

Estas dos líneas lo que nos cuentan es que primeramente dividiremos la tabla Concurso.Localidad por rangos de ID y llamaremos al módulo A de forma paralela para cada brango obtenido, esta computación en paralelo implementada por defecto en IRIS acelerará nuestra consulta sin necesidad de indicarlo.

Como veis nuestra consulta es bastante costosa, ¿a qué es debido? Como podéis ver nuestra consulta está recorriendo por entero la tabla Concurso.Ventas con sus 5 millones de consultas y para cada fila le va a aplicar la condición de que la ciudad sea "Valladolid" y el año determinado. Esto como podéis imaginar no es lo más óptimo. ¿Cómo podríamos mejorar el rendimiento?

 

Añadiendo índices

Como bien sabréis, indexar una columna nos permitirá mejorar el rendimiento de aquellas consultas que contengan una condición sobre dicha consulta, por lo que vamos a probar incluyendo un índice sobre nuestra columna Anyo de nuestra tabla Sales.Record:

Creamos nuestro índice del tipo BITMAP ya que contendrá un conjunto bastante pequeño de diferentes valores y mejorará el rendimiento de nuestras consultas sobre un índice normal (aquí podéis leer la documentación asociada).

Este índice no va a modificar el plan de ejecución, pero lo que hará será acelerar la consulta, veamos el resultado:

Como podemos ver nuestro rendimiento ha mejorado, echemos un vistazo al plan de consulta con el índice incluido:

Como podéis ver, en el módulo B ya no leemos la tabla Concurso.Ventas entera con sus 5 millones de registros, si no que mediante el índice extraemos previamente todos aquellos valores con el Anyo 1996, de tal forma que excluimos de la lectura los no coincidentes.

¿Buena mejora, no? Pero no nos quedemos aquí, podemos mejorar más aún con el...

 

Optimizador de consultas

InterSystems IRIS nos proporciona un optimizador de consultas por defecto que utilizará determinadas herramientas de cara a definir el plan de consulta, no es lo mismo realizar una consulta directamente sobre la tabla con 5 millones de registros de ventas que hacerlo primero sobre la de localidades y a continuación sobre la de ventas excluyendo los registros que no pertenezcan a la localidad solicitada.

La forma más sencilla de optimizar las tablas es ejecutando un sencillo TUNE TABLE sobre la tabla que queremos optimizar. Este comando nos configurará en la definición de la clase de nuestra tabla los siguientes parámetros:

  • ExtentSize: este parámetro contendrá el número de filas de la tabla, podemos definirlo nosotros mismos poniendo el valor que queramos siempre y cuando guarde una proporción con los valores reales respecto a las demás tablas,
  • Selectivity: el porcentaje que representa cada distinto valor de la columna respecto al total, es decir, si tenemos sólo 2 tipos de valores su Selectivity será el 50%, si tenemos 64 como el caso de las localidades será 1.56% si no tenemos valores repetidos.
  • BlockCount: con el valor estimado de bloques del mapa que usará por cada mapa de SQL basado en el ExtentSize.

Echemos un vistazo a la sección Storage de la clase Concurso.Ventas antes de aplicaciar el tunning a la tabla:

Storage Default
{
<Data name="VentasDefaultData">
<Value name="1">
<Value>%%CLASSNAME</Value>
</Value>
<Value name="2">
<Value>SumaVentasMensuales</Value>
</Value>
<Value name="3">
<Value>%Source</Value>
</Value>
<Value name="4">
<Value>Mes</Value>
</Value>
<Value name="5">
<Value>Año</Value>
</Value>
<Value name="6">
<Value>CodigoCiudad</Value>
</Value>
</Data>
<DataLocation>^Concurso.VentasD</DataLocation>
<DefaultData>VentasDefaultData</DefaultData>
<ExtentSize>2000000</ExtentSize>
<IdLocation>^Concurso.VentasD</IdLocation>
<IndexLocation>^Concurso.VentasI</IndexLocation>
<SQLMap name="AñoIdx">
<BlockCount>-10634</BlockCount>
</SQLMap>
<StreamLocation>^Concurso.VentasS</StreamLocation>
<Type>%Storage.Persistent</Type>
}

Como podéis ver tiene una serie de valores por defecto que no ayudarán a mejorar nuestras consultas sobre ella. Ejecutemos el comando TUNE TABLE para ambas tablas y veamos que consecuencias tiene tanto sobre nuestra clase como sobre nuestra consulta.

Veamos nuestra sección Storage:

Storage Default
{
...
<ExtentSize>6468826</ExtentSize>
<Property name="Año">
<AverageFieldSize>4</AverageFieldSize>
<Histogram>...</Histogram>
<Selectivity>2.9412%</Selectivity>
</Property>
<Property name="CodigoCiudad">
<AverageFieldSize>6.7</AverageFieldSize>
<Histogram>...</Histogram>
<Selectivity>3.3333%</Selectivity>
</Property>
<Property name="Mes">
<AverageFieldSize>3</AverageFieldSize>
<Histogram>...</Histogram>
<Selectivity>8.3333%</Selectivity>
</Property>
<Property name="SumaVentasMensuales">
<AverageFieldSize>5</AverageFieldSize>
<Histogram>...</Histogram>
<OutlierSelectivity>.000393:794574</OutlierSelectivity>
<Selectivity>0.0002%</Selectivity>
</Property>
<SQLMap name="$Ventas">
<BlockCount>-48</BlockCount>
</SQLMap>
...
}

Ahora tanto Concurso.Localidad como Concurso.Ventas están correctamente configuradas, veamos su impacto en el plan de ejecución de la consulta:

La mejora es de un 31% respecto a la consulta anterior, y su coste es menos de la mitad de la consulta original, veamos cuanto tarda ahora nuestra consulta:

Así es, como podéis ver hemos pasado de 8 segundos inicialmente a 4.6 incluyendo los índices adecuados a nuestras tablas a poco menos de 1 segundo aplicando TUNE TABLES.

Podéis consultar en está página más posibles optimizaciones para vuestras consultas como por ejemplo %FirstTable, que forzará al optimizador a leer la tabla seleccionada en primer lugar y que puede resultar interesante para limitar las lecturas sobre aquellas tablas de grandes dimesiones filtradas por valores procedentes de la seleccionada.

 

Almacenamiento columnar o Columnar Storage

InterSystems IRIS no sólo nos proporciona las anteriores herramientas para sacarle el máximo partido a nuestras consultas, sino que también pone a nuestro alcance la funcionalidad de almacenamiento columnar destinado para casos como el ejemplo utilizado para este artículo, grandes volúmenes de datos superior al millón de registros sobre el que queremos realizar operaciones de agregación como SUM o AVG.

Este almacenamiento columnar lo podemos definir a nivel de tabla o bien a nivel de columna, como más nos interese. Para que se entienda mejor que es el almacenamiento columnar usaré una imagen de la propia documentación de ISC.

Atendiendo a la explicación podréis ver como para nuestro ejemplo puede ser interesante definir la columna de ventas mensuales como un almacenamiento de tipo columnar, para ver las diferencias he vuelto a montar de 0 las tablas sin índices y sin la ejecución del TUNE TABLE.

El único cambio necesario en Concurso.Ventas para que nuestra columna SumaVentasMensuales utilice el almacenamiento columnar será definir la siguiente propiedad:

Property SumaVentasMensuales As %Integer(STORAGEDEFAULT = "columnar");

Comprobemos ahora el plan de la consulta.

El coste de nuestra consulta con almacenamiento columnar es de 65.487.882, mientras que con almacenamiento en filas era de 100.529.682, una mejora sustancial únicamente modificando el tipo de almacenamiento a utilizar. Veamos cuanto tarda la consulta en ejecutarse:

Algo más de 1 segundo comparado con los más de 8 segundos que tardó con el almacenamiento vectorial.

 

Cierre y despedida

Aquí terminamos este artículo sobre optimización de consultas SQL con InterSystems IRIS que espero os haya resultado de utilidad.

Comentarios (0)1
Inicie sesión o regístrese para continuar
Artículo
· 29 mayo, 2024 Lectura de 3 min

Wall-M : Performe consultas semânticas na caixa de entrada do seu email e tenha respostas acuradas com citações de fontes

 

Introdução

Com o crescimento da Gen AI, acreditamos que agora os usuários devem ser aptos a acessar dados não estruturados de uma maneira muito mais simples. A maioria das pessoas tem muitos emails que não conseguem dar conta. Por exemplo, em investimentos/trading, os profissionais dependem de decisões rápidas que levem em consideração o máximo de informação possível. Da mesma maneira, empregados seniores em uma startup lidando com muitos times e disciplinas podem ter dificuldade em organizar todos os emails que recebem. Esses problemas comuns podem ser resolvidos usando GenAI e ajudar a fazer suas vidas mais fáceis e organizadas. A possibilidade de alucinação em modelos GenAI pode ser assustadora, e é aí que a pesquisa RAG + Hybrid aparece para salvar o dia. É isso que nos inspirou a construir o produto WALL-M (Work Assistant LL-M: Assistente de trabalho LLM - Large Language Model: Grandes modelos de linguagem).  No HackUPC 2024, desenvolvemos o WALL-M como parte do desafio de pesquisa por vetores InterSystems É uma plataforma de geração de recuperação aumentada (RAG - Retrieval Augmented Generation), desenhada para responder perguntas de forma acurada em emails com o mínimo de alucinações possíveis. Essa solução endereça o desafio de lidar com longos e numerosos emails, especialmente em áreas movidas pela velocidade, como investimento e trading, startups com muitos times e disciplinas, ou indivíduos que procuram administrar suas caixas de entrada cheias.

 

O que ele faz

Você pode carregar os emails da sua caixa de entrada e escolher filtrar por data e remetentes para definir o contexto para o LLM. Então, dentro do contexto, você pode escolher consultas específicas relacionadas aos emails escolhidos. Exemplo 1: ideias de trading baseadas em selecionar relatórios bancários ou relatórios de pesquisa de investimento. Exemplo 2: Um funcionário em uma companhia/startup pode pedir uma lista de itens de ação baseados nos emails relacionados a trabalho recebidos na última semana.


Depois disso, se você tiver quaisquer outras questões, também adicionamos um segmento para conversar com o Wall-M, baseado no contexto selecionado usando a consulta inicial. Isso assegura que todas as questões subsequentes também receberão respostas que não alucinam e incluem os emails fonte usados para gerar a resposta.
 

Como construimos ele

Frontend: Taipy

Backend: InterSystems Database, SQL

RAG + Vector Search: InterSystems Software, ChatGPT

Tools: LangChain, LlamaIndex

 

Desafios que encontramos

Aprender a usar com a framework (estrutura) de Python full-stack "TaiPy". Otimização de prompt para evitar alucinações. Usar LangChain para obter um padrão específico que inclui citações apontando para a fonte da resposta/alegação. Incompatibilidades entre diferentes ferramentas que queríamos usar.

Próximos passos para o Wall-M

Usar a prova de conceito para os casos de uso específicos e avaliar sua performance usando benchmarks  para validar a credibilidade do produto. Melhorar a integração com aplicações comuns de emails como Outlook e Gmail com usos personalizados para melhorar a utilidade do Wall-M.

Teste você mesmo

Nosso repositório GitHub : https://github.com/lars-quaedvlieg/WALL-M

Comentarios (0)1
Inicie sesión o regístrese para continuar