sábado, julio 09, 2005

Cronica de una migración exitosa, Parte 2

Parte 2. La base de datos:

Cuando pretendes ganarte la vida vendiendo software, hay muchas cosas a tomar en cuenta en cuanto a diseños, estrategias de mercadeo, etc. Una de ellas es la base de datos. Pocos son los sistemas que veremos en el mercado cuyo fin no sea almacenar datos, de una forma u otra todos lo hacen.

Quizá te hayas encontrado muchas veces, cuando vas a vender un desarrollo, la pregunta típica de todo aquel que siente tener los conocimientos necesarios de informática por el simple hecho de trabajar todos los días con una computadora:

¿ En que está hecho ?
¿ Con qué base de datos trabaja ?

En realidad estas preguntas deberían ser las menos hechas, en mi opinión las preguntas correctas serían... ¿ hace realmente bien las cosas ?, ¿ es rápido y fácil de usar ?.

Todos hemos visto caras de "estás obsoleto" cuando le comentas a alguien que tu sistema está hecho en Clipper con archivos DBFs, inmediatamente todo el mundo te ve con cara de Parque Jurásico, por eso ahora, para evitarnos el mal trago, simplemente decimos: Esta hecho en Borland C++... ¡¡¡ y que me digan que no es cierto !!!, no va a faltar el listillo que va a preguntar... ¿ a ver el código fuente ?, no importa, muestrale el PCODE que genera xHarbour, seguramente la siguientes expresión será .... si si, ya se nota que está hecho en "C" ( si yo sé "C", ¿ quien contra mi ?).

El Software de Sanrom's va por la version 5.x, y la nueva versión de 32 bits será la 6, y en todas las versiones anteriores se habían utilizado archivos DBFs, con índices CDX, trabajando todo el software para red.

El cambio a 32 bits se quiso aprovechar para hacer un cambio también en el esquema de almacenamiento de datos, por muchas razones que iremos analizando mas adelante.

Desde la version 1.x de los sistemas Sanroms, Israel me había estado insistiendo en que su gran preocupación eran los archivos de datos, que el volúmen aumentaba en proporciones moustrosas cada mes, y por lo mismo se hacía mas lenta la ejecución del programa, lo cual está claro, en un colegio de 2,500 alumnos, donde cada alumno lleva un promedio de 10 materias, se generan mensualmente 25,000 registros de datos sólo para calificaciones, si multiplicamos eso por 10 meses de actividad docente al año, llegaremos a la conclusión de que se generan sobre 250 mil registros de datos en un período lectivo anual, y si a eso aunamos que hay que guardar históricos de por lo menos 5 años, tenemos que el archivo de calficaciones tendra algo así como 1'250,000 registros, el archivo de calificaciones genera tambien por lo menos 10 pagos anuales, multiplicados por 2,500 alumnos, esto nos da un total de 25,000 registros solo de pago de colegiatura normal, pero ademas hay otros tipos de pago como reposición de credencial, estacionamiento, actividades extraescolares, etc. asi que no solo son los 25,000 registros anuales de colegiaturas, son un poco mas.... y eso que no hemos contado todos los registros adicionales que se van generando con el uso del sistema como por ejemplo maestros, bitacoras, materias, horarios, etc. etc. etc.

Si a eso agregamos que nunca falta el usuario con iniciativa que le mete mano a los DBFs con Excel y luego se da el lujo de decirle a Excel que quiere guardar el archivo (ha sucedido más de una vez) y la corrupción de índices, que nunca debe faltar en un buen sistema... llegamos a la conclusión de que el almacenamiento de datos debía recibir una buena revisión.

Desde la version 4.x de los sistemas yo le había sugerido a Sanroms utilizar Advantage Database Server para garantizar la seguridad de la base de datos, y en ese entonces intentamos hacer la migración, sin embargo, tuvimos graves problemas con la clase TSBrowse a 16 bits y dado que el sistema está basado en un 80% en esa clase, desistimos en el intento.

La idea de utilizar ADS ya le venia dando la vuelta en la cabeza a la gente de Sanroms desde hace mucho tiempo, y así pues, para la versión de 32 bits se decidió que el código de esta nueva versión seria totalmente optimizado para utilizar ADS y se aprovecharía al maximo el RDD ADS con todas las funciones que tiene implementadas.


¿ Porqué ADS y no un SQL ?

La respuesta es sencilla, todos los datos actuales de los usuarios de los sistemas de Sanroms están guardados en DBFs, el camino lógico de migración hacia una herramienta mas "potente" con tecnología Cliente/Servidor, es ADS, desde el punto de vista de que no hay que hacer migración de datos, el usuario final seguirá trabajando con sus mismos datos y metodologías pero con un mejor manejo de sus tablas DBFs.

Otra razón para utilizar ADS, era que no había que hacer grandes cambios en el código fuente para el acceso a los datos, es decir, las operaciones actuales de lectura/escritura de los datos a las tablas permanecerían sin cambio, con lo cual habia un ahorro significativo en tiempo de programación, cambiar a un SQL hubiera significado volver a tener que escribir todas las rutinas de acceso a los datos y eso llevaría mucho, mucho, mucho tiempo adicional, porque tendríamos que rediseñar la base de datos primero y luego tendriamos que adaptar el programa a las nuevas estructuras de tablas (conozco empresas que llevan mas de un año intentando hacer funcionar un programa que usaba DBFs ahora con SQL y no terminan, y van como para otro añito mas o así).

Otra razón para utilizar ADS fue la portabilidad entre sistemas operativos de red, si hay una cosa en la que los colegios no gastan, es en tecnología, luego entonces no todos los colegios tienen servidores Windows NT, los hay que tienen Novell, otros que tienen Linux y otros menos agraciados, que trabajan con redes punto a punto con Windows 9x o XP, sin servidor dedicado. Si usábamos MySQL podíamos usarlo en Windows y en Linux pero no en Novell, si usábamos SQL Server podíamos usarlo en servidores Windows, pero no en Linux y tampoco en Novell, si usabamos Oracle, poíiamos utilizarlo en todos los servidores, pero el precio de la base de datos se disparaba hasta las nubes.... ¿ solución ?: Nuevamente ADS, es el único servidor de datos que tiene versiones para TODOS los sistemas operativos de red: Novell desde la versión 4.x, Windows NT/2000/2003 Server, Linux y hasta para redes punto a punto con Windows 9x.

Por otro lado ADS puede ser utilizado por cualquier lenguaje de programación, ya que soporta sentencias SQL para manipular las tablas, esto le permite a otros sistemas dentro del mismo colegio convivir e intercambiar datos con las tablas de los sistemas Sanroms.

El gran obstáculo en este punto, fue el precio del servidor de datos, que fue un problema relativo, los colegios pequeños, con pocos alumnos y por ende pocos usuarios, usarán el servidor local de ADS que es gratis y que puede manejar perfectamente hasta 5 usuarios simultáneos, claro, no tiene todas las grandes ventajas del servidor profesional, pero se puede trabajar con él muy bien y facilita la migración al servidor remoto (profesional) de una manera transparente en un futuro, si el colegio así lo decide. Los colegios mas grandes y con mayor número de usuarios (y con mas alumnos, por lógica) no tendrían ningún problema en adquirir servidores profesionales ADS, de hecho por lo menos 5 ya han pedido cotización.

Preparándose para ADS.

Mucha gente que ha utilizado el servidor local de ADS se queja de la lentitud del mismo, sin embargo no se dan cuenta de que para aprovechar todas las ventajas de ADS, hay que seguir algunas reglas básicas de uso.


Apertura de Archivos.

Por ejemplo, bajo ADS es necesario abrir TODAS las tablas de trabajo al principio del programa y no como en Clipper estamos acostumbrados, es decir, a abrir las tablas conforme las vamos necesitando y cerrándolas en el momento en que terminamos de usarlas, existen razones válidas para hacer esto, la mas común de todas es para evitar la corrupción de índices, entre menos tablas tenga abiertas, menos índices se pueden dañar, (lo cual es una reverenda tontería, cuando hay un índice dañado usualmente no regeneramos solo el índice dañado, regeneramos TODOS los índices de TODAS las tablas "por si las dudas", asi que... si de todas formas vamos a regenerar TODOS los índices en caso de daño, ¿ qué mas da que se dañe uno o todos ? ).

La segunda razón para esta serie de operaciones de Apertura/Cerrado de archivos DBFs, se debe a la limitación de los sistemas de 16 bits con respecto al número de archivos que se pueden abrir simultáneamente, los famosos FILES y BUFFERS de Clipper. Aunque en teoría Clipper puede abrir 255 archivos al mismo tiempo, esto no es del todo cierto, está limitado a una serie de parámetros en el CONFIG.SYS que determinan el número máximo de archivos que se pueden abrir y usalmente, a 16 bits, ese número está limitado por la memoria que la computadora.

A 32 bits no hay limitación en el número de archivos a abrir simultáneamente, así que la primer labor de programación para optimizar el código de Sanroms para usar ADS, fue eliminar TODOS los USE dentro del código del programa, y creánme, no fue una labor fácil porque había que revisar miles de líneas de código. También hubo que crear una rutina que abriera TODOS los archivos de datos junto con sus índices de una sola sentada, al arrancar el programa, sin embargo, el realizar estas operaciones llevó a mejorar el control de "alias" de las tablas porque permitió asignar "alias" fijos a los archivos abiertos, que nunca cambiarían durante toda la ejecución del programa. A nivel de arquitectura de ADS, este cambio optimizó enormemente el uso del servidor, ya que el servidor (local o remoto) solo recibe una petición de apertura por estacion de trabajo, esto le permite despachar los datos con mayor rapidez, ya que al tener abierto un archivo de datos en el servidor ADS, no es necesario volverlo a abrir por cada petición de la estación de trabajo, en cambio, si abrimos y cerramos continuamente archivos, estamos sobresaturando al servidor ADS de solicitudes de apertura y cerrado y por lógica reduciendo el rendimiento del mismo. En las pruebas realizadas en red, una vez realizada esta operación de optimización , tanto con el servidor local como remoto, se observó un comportamiento similiar en velocidad en el acceso a los datos.

Indices y Funciones definidas por el usuario.

Otro cambio necesario fue hacer una revisón a las llaves de los índices en busca de "FDUs" (Funciones Definidas por el Usuario), ADS no soporta que una llave del índice sea una función definida por el usuario, por ejemplo:

INDEX ON SumaNombre(appaterno,apmaterno,nombre) TAG NomCompleto

Esto no es una expresión válida para el motor de indexación de ADS ¿ porqué ?, pues porque la función SumaNombre() no es reconocida por ADS, recuerda que ADS es un programa EXTERNO a tu aplicación y no puede interactuar con ella, de tal forma que si el código fuente de la función SumaNombre() forma parte de tu archivo EXE en xHarbour, el servidor de ADS no tiene forma de "meterse" en tu archivo EXE para ver que operaciones realiza la función y ver que valor devuelve. Para solucionar este problema simplemente se agrega un campo nuevo al DBF, llamado por ejemplo NomCompleto, y al momento de hacer el REPLACE de los datos, se hace un llamado la función SumaNombre, así:

REPLACE NomCompleto WITH SumaNombre(appaterno, apmaterno, nombre)

Y luego, se genera un índice normal sobre ese campo:

INDEX ON NomCompleto TAG NomCompleto

De esta forma tenemos solucionado el problema (parcialmente), aún tenemos que ver que pasa con esos índices temporales que se generan con el fin de "filtrar" una base de datos.

AOFs, Filtros Optimizados Advantage.

Durante toda nuestra vida de Clipperos hemos aprendido que SET FILTER no es precisamente la mejor manera de filtrar los datos cuando se requiere solo un pequeño grupo de ellos dentro de una tabla y que la peor combinación que se puede hacer es mezclar un SET FILTER con un BROWSE, eso mas lento que el caballo del malo en una película de vaqueros.

Los índices CDX nos abrieron las puertas al maravilloso mundo de los SCOPES, un simple SET SCOPE TO y los filtros sobre las tablas se hacen a la velocidad del rayo, el precio a pagar.... agregar un índice al CDX sobre el campo que queremos filtrar, al parecer, hemos triunfado, peroooooooo......

¿ Que pasa si el criterio de filtrado no está dentro de un índice o bien esta en razón de una variable del programa ?, ¿creamos un índice "al vuelo" ?, no es mala idea, pero eso lleva tiempo.... ¿ que hacemos entonces ?.

Si fuesemos programadores de dBase III+ recurriríamos al SET FILTER sin importar cuanto tiempo se lleve el dichoso filtro, pero ADS nos regala una cosa llamada AOFs (Advantage Optimized Filters = Filtros Optimizados Advantage), característica incluída tanto en el servidor local como en el remoto.

Un AOF es un "filtro" que es realizado por el servidor ADS directamente, no por tu programa xHarbour. Un AOF se ejecuta con la misma velocidad que un query de SQL, y devuevle resultados de una manera muy rápida, la gracia de utilizar un AOF, consiste en saber crear el filtro.

Supongamos que tenemos el siguiente pedazo de código:

nEdad := 25
SET FILTER TO EmpEdad >= nEdad

Esto funcionaría en Clipper normal, pero no con ADS, ¿ porqué?, pues porque ADS no conoce el valor de la variable nEdad y por lo mismo no puede "resolver" el filtro de una manera adecuada, para utilizar un AOF, debemos de pasarle al servidor ADS la expresión "digerida", es decir con los valores que tiene que buscar, en forma textual, esto se hace creando una cadena de caracteres que contenga la expresión de filtro:

nEdad := 25
cFiltro := "EmpEdad >="+ALLTRIM(STR(nEdad))

Esto crea una cadena de caracteres con la expresión de filtro, para enviarsela al "motor" de AOFs, lo haremos mediante la función DBSETFILTER() como bloque de código y también como cadena de caracteres:

cBloque := "{"+cFiltro+"}"
DBSETFILTER(&cBloque,cFiltro)
DBGOTOP()


Esta simple operación realizará un AOF sobre la tabla DBF la velocidad de este tipo de filtro es IMPRESIONANTE, casi igual de rápido que un SCOPE.

Así pues, se revisó TODO el código para implementar AOFs en todas aquellas partes que se pudieran ver beneficiadas de su uso.


El divorcio del DBF.

Durante el proceso de optimización del código para ADS y viendo todas las bondades que iba arrojando la implementación dentro de los sistemas, nos asaltó la duda.... ¿ y si mejor utilizamos tablas ADT con índices ADI en vez de DBFs con índices CDX ?.

La idea no se quedó mucho tiempo en el aire, usando el ARC (Advantage Data Architech), una herramienta similar al DBU pero para ADS, exportamos todas las DBFs a archivos ADT y nos encontramos con varias sopresas:

La primera fue que la tabla ADT está mas optimizada que el DBF tradicional, es aproximadamente 10% mas pequeña que su similar DBF con el mismo número de registros.

La segunda fue que la tabla ADT funciona mas rápido que el DBF, es decir, que la recuperación de datos usando el servidor ADS sobre una tabla ADT con índices ADI es mas rápido que sobre un DBF con índices CDX.

La tercera fue que la tabla ADT no se puede abrir mas que con el ARC, ni Excel la puede abrir, con lo cual alejabamos de las ojos curiosos y de los usuarios con iniciativa los datos del sistema.

La cuarta fue muy impactante..... la estructura de la tabla ADT no es igual a la de la tabla DBF tradicional, por ejemplo, un campo que un DBF es un NUMERIC de 2 enteros con 0 decimales, en una tabla ADT es de tipo INTEGER, pero un campo que sea un NUMERIC de 10 enteros con 2 decimales en ADT es un campo tipo FLOAT, lo mas curioso de esto es que la función DBCREATE() de xHarbour, puede recibir una estructura de DBF como parametro, y la tabla ADT resultante tiene OTRA estructra distinta, de acuerdo al esquema de almacenamiento de las ADT, esto no tiene la menor importancia en la operación del programa porque de hecho no hay diferencia en el manejo de los campos, se leen y se escriben de la misma manera que un DBF, es mas, si un campo es, por ejemplo, de tipo FLOAT y se asigna a una variable como se hace normalmente, se trabaja como un NUMERIC común y corriente. A los sistemas Sanroms, esto le afectó porque cuenta con un "verificador" de estructuras, es decir, un modulo que verifica que la estructura de los archivos de datos sea la correcta para utilizar el sistema, pero esta rutina verificaba sobre estructuras DBF, no sobre ADT por lógica ese módulo SIEMPRE reportaba problemas con la base de datos, la solución fue simple, se cambió el programa para verificar las estructuras sobre los tipos válidos de ADT y asunto arreglado.

Otra cosa que se realizó fue la creación de un pequeño módulo externo que "migrara" los DBFs a tablas ADTs, este pequeño módulo migra todas las tablas del sistema en menos de 5 minutos de DBF a ADT, por la parte de los índices no hay el menor problema tampoco, estos se generan utilizando los comandos y funciones que se utilizan normalmente con índices CDX, es decir INDEX ON .... TAG .......

Lo bueno de cambiar a tablas ADT fue que mejoramos la velocidad de acceso a los datos, protegimos los datos de miradas curiosas y de herramientas que pueden manipular los archivos y lo mejor de todo: No tuvimos que mover nada del código que lee y escribe los datos a los archivos, osea que APPEND y REPLACE siguen funcionando.

Todo o nada, implementando transacciones.

Una de las cosas mas interesantes de ADS y mas útiles son las TRANSACCIONES, una transacción en terminos simples, son un grupo de operaciones sobre las tablas de la base de datos que se tienen que realizar TODAS hasta completarse, por ejemplo, en el caso de la elaboración de una factura, se tocan varias tablas, de unas se traen datos, por ejemplo de la de clientes, en otras se alteran valores de los campos, como por ejemplo en los inventarios y cuentas por pagar, en otras se agregan nuevos registros, como por ejemplo en la contabilidad, bueno todas esas operaciones que afectan las distintas tablas se conocen dentro de ADS como una TRANSACCION.

ADS tiene un control de transacciones que se implementa mediante 2 comados BEGIN TRANSACTION y COMMIT TRANSACTION, mediante estas 2 simples operaciones grantizamos que TODAS las operaciones que deban ser realizadas sobre una grupo de tablas se hagan totalmente hasta completarse, o que en caso de que "algo" falle tanto a nivel hardware, como software, no se realice ninguna de ellas, dejando todas las tablas en el último estado conocido, un esquema comun sería algo como esto:

BEGIN TRANSACTION
SELECT ....
APPEND BLANK
REPLACE....
REPLACE....
REPLACE....
.....
SELECT ....
IF DBSEEK .....
REPLACE....
REPLACE...
ELSE
APPEND BLANK
REPLACE .....
REPLACE ....
ENDIF
COMMIT TRANSACTION

En el esquema anterior y bajo el sistema de transacciones de ADS, TODAS las operaciones de añadir registros y modificar campos se realizaran desde la linea que dice BEGIN TRANSACTION hasta la línea que dice COMMIT TRANSACTION, si algo llegara a ocurrir entre dichas lineas, ya sea un problema de software (un error de sintaxis por ejemplo) o un problema de hardware (una falla en la corriente eléctrica por ejemplo), el servidor ADS DESHACE todo lo que tenga hecho, a esto se le llama un ROLLBACK TRANSACTION, y deja las bases de datos como estaban ANTES de hacer el BEGIN TRANSACTION, esto es fenomenal, porque ya nunca mas nos enfrentaremos a los problemas de bases de datos incompletas o con datos faltantes.

El motor de transacciones solo esta soportado en el servidor remoto ADS, el servidor local, aunque reconoce los comandos BEGIN TRANSACTION y COMMIT TRANSACTION, no ejecuta ninguna accion.

Encriptar o no encriptar.... esa es la cuestión.

Como parte del nuevo sistema de seguridad de ADS, decidimos encriptar las bases las bases de datos, ya que en el remoto caso de que alguien pudiera "robarse" los archivos de base de datos y llevarselos a otra computadora, no pueda ni siquiera leer la información.

El motor de encriptamiento de ADS utiliza un encriptamiento de 128 bits, que adicionalmente no genera el mismo código para la misma letra, digamos por ejempo que se tiene un valor "aaaaaa", ADS encripta la cadena y generaría algo como esto "5&$2q!", es decir, la misma letra no genera el mismo código encriptado, depende de la posición en que se encuentre dentro de la cadena de caracteres original. El sistema de encriptamiento codifica TODOS los tipos de campos, de tal forma que no importa que el campo sea numérico, lógico o cadena de caracteres, todos los datos están encriptados.

Adicionalmente ADS utiliza un algoritmo de encriptamiento de doble llave, donde el programador debe proporcionar un "password" previamente definido por el, este password se utilizará como "semilla" para encriptar la base de datos, la encriptación se realiza a nivel área de trabajo, con lo cual se pueden tener disitintos passwords para las distintas áreas de trabajo, de esta forma, aun en el caso de que alguien se robe los archivos, no le será posible visualizar la información , necesitaria 2 componentes: el motor de ADS y el password correcto.

La encriptación se realiza por medio del servidor ADS (local o remoto, esta características está incluida en ambos), mientras el archivo permanece encriptado en disco, es el servidor ADS quien hace el proceso de encriptado/desencriptado y envía a las estaciones de trabajo los datos desencriptados para su correcta visualización y los datos recibidos de las estaciones son encriptados por el mismo servidor para guardarlos en el archivo físico en disco.

La encriptación trajo un problema adicional, los comando COPY TO y APPEND FROM requieren que los datos sean desencriptados para poder exportarlos a nuevos archivos que puedan ser leidos.

Otras cosas a tomar en cuenta:

NULL no es lo mismo que vacío.... NULL es un valor que manejan muchas tablas SQL, un campo vacío en un archivo ADT no tiene un valor "vacío", sino que tiene un valor NULL, que es un valor neutro (como NIL) pero que a fin de cuentas es un "valor", esto nos complico un poco la vida al momento de hacer filtros o índices utilizando EMPTY(campo), sucede que los campos vacíos no respentan esta condición, porque en realidad no estan vacíos, tienen NULL, luego entonces la solución fue llenar estos campos vacíos con cadenas de caracteres vacías, o bien ceros en el caso de los campos numéricos.

¿ Cómo editar los datos ?.... Esa fue otra, con DBFs tenemos un gran número de editores para manejar los datos, el WinDBU, Prometeus, el mismo DBU de Clipper.... Con tablas ADT... ¿ que editor se utiliza ?, pues el mismo que provee ADS, el llamado ARC o Advantage Data Architech.

ARC permite hacer muchas de las labores de mantenimiento de los datos utilizando browses y los menús del programa, cosas mas complejas como reemplazos masivos, borrado de datos y otras similares no pueden realizarse directamente, pero ARC provee de un editor de instrucciones SQL que utilizando sentencias como SELECT, INSERT, UPDATE y DELETE te permite darle mantenimiento a los datos con facilidad, pero eso si, necesitas conocer un poco de SQL.

Si la tabla está encriptada, ARC te pedirá el password para poder abrir cualquier tabla ya sea desde el editor de datos o desde el editor de sentencias SQL, de esta manera, aún si alguien se roba los datos e incluso contando con el ARC, no podrá verlos, porque no tiene los passwords para las disintas tablas.

ARC te permite adicionalmente monitorear el servidor remoto (cuando se tiene instalado), crear "Diccionarios de datos" que son colecciones de tablas con niveles de seguridad a nivel usuario , tabla y registro, como en los SQL profesionales, que se utilizan para el acceso a los datos via internet.... je, olvide mencionarlo, los programas ADS pueden acceder a los datos via internet utilizando un componente incluido en el servidor remoto llamado AIS (Advantage Internet Server).

En realidad la explicación es mas extensa de lo que en realidad se trabajo, todo el proceso de cambio en el código y prueba de las bases de datos con los servidores remoto sy local llevo poco menos de 2 meses.

Una vez concluido con el cambio de formato de base de datos, pasamos a la parte de optimización del código para aprovechar las extensiones de xHarbour, como verás son cosas que el usuario no va a notar, pero que era necesario hacerlas para una migración exitosa a 32 bits.

3 comentarios:

Anónimo dijo...

Rene, la apertura y cierre de las tablas es realmente lo que mas tarda en una aplicación. Dices de abrir TODAS las tablas de golpe al iniciar el programa. OK pero si luego necesito volver abrir una tabla que generara otro alias, esto retarda de nuevo el sistema o como ya esta abierto no le afecta. Lo mismo si he abierto una tabla una segunda vez y luego la debo de cerrar, cierto? puedes detallar un poco esto, como lo haces.
Un saludo y enhorabuena
Jesús Díez González

Anónimo dijo...

Jesús:

La idea de abrir las tablas desde un principio es evitar la apertura y cierre de tablas constantemente, ya que esto retarda por mucho la respuesta del sistema (por lo que veo esto ya lo tienes claro).

Estos alias ya abiertos son los que utilizo en la mayoria de mis procesos. Peerrooo, como tu bien dices, también tengo la necesidad de volver a abrir nuevamente algunas tablas con nuevos alias y cerrarlas al terminar de usarlas.

El abrir nuevamente tablas con otro alias ya no ocasiona tan notable lentitud ya que las tablas YA SE ENCUENTRAN ABIERTAS, y solo se hace una nueva "referencia" a la tabla ya abierta pero con el nuevo alias y al "cerrar" se anula esta referencia.

Espero te sirva mi humilde explicación y ojalá René me corriga si he dicho una barbaridad.

SALUDOS!!

Israel Solis

Ariel dijo...

René:

Estoy haciendo la migración de DBFs con CDXs a ADTs con índices ADIs mediante Harbour.
No me funcionan los DbSeek(), me abre la ADT con el indice pero cuando hago la búsqueda (clave de un solo campo y de tipo caracter) no me encuentra el registro deseado. Si lo abro por el architect me lo encuentra sin problemas.

Que estoy haciendo mal?

Desde ya muchas gracias!