Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Access-VBA: FindFirst muy lento (Access2003 - SQLServer)

337 views
Skip to first unread message

rodeca

unread,
Jul 29, 2008, 1:58:03 PM7/29/08
to
Hola,

Introducción:
no soy ningún experto en Access ni en SQL, pero algo sé. Sobre todo, me
pierdo bastante en los tipos de Recordset... [todo esto no es para llorar a
alguien: es para proporcionar pistas :-)

Tengo una DB en SQLServer2000. Se gestiona con Access2003.
Hay una tabla vinculada ("Tabla1"), con unas 200.000filas, y otra tabla
vinculada ("Tabla2"), con unas 70.000 .
Cada fila de Tabla1 puede tener 0 o varias filas relacionadas en Tabla2. Las
dos comparten la columna "Campo1"
Tabla2 tiene una clave principal formada por Campo1+Campo2

Pues bien:

Un Recordset con una condición de este estilo
| Patata = _
| "SELECT Tabla2.ColuT2_1, Tabla2.ColuT2_2, etc.etc. " & _
| "Tabla1.ColuT1_A, Tabla1.ColuT1_B, etc.etc. " & _
| "FROM Tabla1 INNER JOIN Tabla2 ON Tabla1.Campo1 =
Tabla2.Campo1 " & _
| "WHERE etc.etc. "
| Set rstBusOri = CurrentDb.OpenRecordset(Patata)
se abre inmediatamente y se recorre "con suavidad" (sin esperas
apreciables).

Sin embargo,
| Set rstVie = CurrentDb.OpenRecordset("Tabla2", dbOpenDynaset)
| (... más código ...)
| CondMov = "[Campo1] = " & iPototo1 & " AND [Campo2] = " & iPototo2
| rstVie.FindFirst CondMov
tarda unos *10 segundos* en devolver el resultado.
Y no puedo utilizar rst.SEEK por ser tabla vinculada.

Yo habría supuesto que la INNER JOIN sería más "laboriosa" para ellos...
pues ¡parece que no!
Yo había pensado en un problema de "bloqueos", pero la aplicación que se usa
para esa BD está accesible a muchos usuarios simultáneos y cada vez que
presenta una fila de Tabla1 presenta también todas las filas de Tabla2
relacionadas
(con otro recordset WHERE Tabla2.Campo1 = iPatata).

Creo que me he enrrollado. Lo siento. ¿Alguna pista sobre esos 10 segundos?

Muchas gracias por intentarlo (y más gracias todavía si lo consigues)
Rodeca

Antonio Ortiz

unread,
Jul 29, 2008, 6:17:38 PM7/29/08
to

En la segunda opcion estan abriendo toda la tabla!, lo cual es un grandisimo
error, pues significa trasladar toda la tabla desde el servidor al cliente y
enseguida buscar entre todos los registros los requeridos.


Antonio Ortiz
asesor en sistemas
ant(a)aortiz.net
www.aortiz.net
www.progvisual.com

"rodeca" <rodeca...@terra.PATATA.es> escribió en el mensaje
news:erumLTa8...@TK2MSFTNGP05.phx.gbl...

rodeca

unread,
Jul 30, 2008, 4:14:18 AM7/30/08
to
Perdona, no me expliqué bien:
Lo que tarda 10 segundos no es el OpenRecordset: eso lo hace una vez al
principio y sí tarda como un segundo. Lo malo son los rst.FindFirst.
Yo me estoy temiendo que Access no le "encargue" esa búsqueda a SQLServer,
sino que Access se esté recorriendo todas las filas y haciendo él el
filtrado. Desde luego, hay tráfico en la red del cliente durante toda la
espera. Pero, si es así, ¡vaya patata de cliente-servidor!.

Voy a probar un truco que encontré ayer en mvps.org para abrir el rst en
modo tabla. Os mantendré informados: ¡sé que os apasiona! :-p

Gracias, Antonio
Rodeca


"Antonio Ortiz" <a...@aortiz.net> escribió en el mensaje
news:uj3esjc8...@TK2MSFTNGP03.phx.gbl...

Patxi Sanz

unread,
Jul 30, 2008, 10:15:13 AM7/30/08
to
Como dice Antonio, en la segunda opción recoges todos los registros,
100.000. Y FindFirst tiene que ir recorriendo el Recordset hasta encontrar
el primer registro según el criterio indicado. Es ahí donde te aparecen esos
10 segundos de demora. Y por eso es más rápido cargar el Recordset con un
WHERE: para que sea el servidor el que se encargue de filtrar los registros.

Más información de FindFirst, sacada de la ayuda de DAO:

[...]
Utilizar los métodos Find con conjuntos de registros de ODBC conectados a
Microsoft Jet puede no ser eficaz. Es posible que expresar con otras
palabras los criterios para localizar un registro específico es más rápido,
sobre todo cuando se trabaja con un número de registros.
[...]
Cuando trabaje con bases de datos Microsoft Jet conectada a ODBC y hojas de
respuesta dinámica grandes, los objetos Recordset que podría descubrir que
utilizar los métodos Find o utilizar la propiedad Sort o Filter es más
lento. Para mejorar el rendimiento, utilice consultas SQL con las cláusulas
ORDER BY o WHERE personalizadas, consultas de parámetros o los objetos
QueryDef que recuperan registros indexados específicos.
[...]
Para un mejor rendimiento, el criterio debería estar en el formato "campo =
valor" donde campo es un campo indexado el la tabla base o "campo LIKE
prefijo" donde campo es un campo indexado de la tabla base y prefijo es un
prefijo de una cadena de búsqueda (Por ejemplo, "ART*").
[...]

--
Un saludo,


Patxi Sanz
patxisanz[ARROBA]yahoo[PUNTO]es
http://es.geocities.com/patxisanz/index.html
Tudela (NA)

rodeca

unread,
Jul 30, 2008, 10:44:12 AM7/30/08
to
En efecto, al final lo que he hecho es ejecutar cada vez un SELECT y poner
esa condición en WHERE (que además es una condición "=").

No lo había hecho antes porque,
- para mi mentalidad de señor mayor :-p, "abrir ficheros" es lo lento
- no creía que el Findfirst fuera tan torpe: creía que le pasaría la
petición a SQL (como sí hace en SELECT).

Gracias de nuevo, a ambos
Rodeca

P.D. No se lo digáis a nadie, pero es que todavía no sé cuándo algo es JET
y/o ODBC y/o ODBCDirect. Menos mal que este proceso es para una "limpieza"
que se hace 2 ó 3 veces al año y el rendimiento no es algo crítico.

"Patxi Sanz" <patxisanz[ARROBA]yahoo[PUNTO]es> escribió en el mensaje
news:OlARt6k8...@TK2MSFTNGP04.phx.gbl...

Patxi Sanz

unread,
Jul 31, 2008, 5:42:12 AM7/31/08
to
FindFirst busca en el conjunto de registros, no le pasa la petición al
servidor. Por eso es tan lento :-(

De la ayuda de DAO:

- motor de base de datos Microsoft Jet: Sistema de administración de bases
de datos que recupera datos de y almacena datos en bases de datos del
sistema y de los usuarios. El motor de base de datos Microsoft Jet se puede
ver como un componente administrador de datos con el que se crean otros
sistemas de acceso a datos, como Microsoft Access y Visual Basic.

- origen de datos ODBC: Término utilizado para hacer referencia a una base
de datos o a un servidor de bases de datos utilizado como origen de datos.
Los orígenes de datos se refieren mediante su Nombre de origen de datos. Los
orígenes de datos ODBC se pueden crear utilizando el Panel de control de
Windows o el método RegisterDatabase.

- espacio de trabajo de Microsoft Jet: Espacio de trabajo que utiliza el
motor de bases de datos Microsoft Jet para tener acceso a un origen de
datos. El origen de datos puede ser un archivo de bases de datos de
Microsoft Jet (.mdb), una base de datos de ODBC, como una base de datos de
Paradox, o una base de datos de ISAM.

- espacio de trabajo de ODBCDirect: Espacio de trabajo que utiliza
ODBCDirect para tener acceso directo a un origen de datos ODBC, evitando el
motor de bases de datos Microsoft Jet.

Que más o menos viene a decir: Jet es la "aplicación" con la que nos
conectamos a una base de datos, ya sea Access, SQL Server o cualquier otro
tipo de base de datos. ODBC (Open Database Conectivity), es una serie de
elementos que indican la base de datos: ubicación, servidor, tipo de base de
datos, a la que nos queremos conectar. Y ODBCDirect es una conexión directa
a la base de datos, en la que no usamos Jet.

Normalmente, se usa Jet directamente para acceder a bases de datos Access,
mientras que con ODBC a través (o no) de Jet, nos conectamos a bases de
datos tipo SQL Server, MySql, etc.

Como siempre, puede haber excepciones, o puede ocurrir que se use OLE DB en
vez de ODBC, que es otro sistema para acceder a una base de datos mediante
los objetos de ADO.

rodeca

unread,
Jul 31, 2008, 10:39:57 AM7/31/08
to
Ok, gracias.
Ro
P.D. Es que leyendo el manual ¡así cualquiera!

"Patxi Sanz" <patxisanz[ARROBA]yahoo[PUNTO]es> escribió en el mensaje

news:uYZN1Gv8...@TK2MSFTNGP05.phx.gbl...

Patxi Sanz

unread,
Jul 31, 2008, 11:23:02 AM7/31/08
to
:-)
0 new messages