Surviving the Night

El blog de Pablo Doval sobre .NET, SQL, WinDbg...

Speed of Light: ¿Usa el DataReader cursores?

Hace unos días tuve una agradable conversación con unos compañeros que nos acabó llevando al espinoso asunto del uso de los cursores... momento en el cual este tipo de conversaciones suelen dejar de ser tan agradables y pasan a la categoría de Guerras de Religión (ya sabéis, cursores siempre vs. cursores nunca, vi vs. emacs, Windows vs. GNU/Linux y como no, el rey de las guerras de religión... Aritos de Cebolla vs. Fingers de Mozarella).

El caso es que yo, habiendo entrado en modo talibán durante el ejercicio de mis labores como detractor del empleo de los cursores, estaba defendiendo que no era la mejor de las ideas utilizar cursores para un proceso que podría trabajar potencialmente con millones de filas. Me quedé sorprendido cuando otro chico me comentó que los DataReaders de .NET estaban implementados mediante cursores, y ciertamente recordaba haber leído algo similar durante mi formación en ADO.NET, por lo que volví a la documentación de la MSDN y pudimos comprobar cómo los DataReaders funcionan mediante cursores forward-only, read-only.

Antes de que hubiéramos terminado de leerlo ya teníamos a Unai picando un código de demo :_) Cuando la terminó, la ejecutamos y monitorizamos su ejecución mediante el SQL Profiler (capturando eventos de cursores de servidor y de cliente... aunque los de servidor no debería aparecer nunca con ADO.NET, pero por si las moscas ;)), el performance monitor de windows (perfmon.exe) y las vistas de administración dinámicas de SQL Server 2005, y no pudimos apreciar la creación de un solo cursor.

Por una parte fue un alivio (nos parecía overkill que se crearan cursores con todos los DataReaders), pero por otra parte resultó bastante desconcertante el hecho de que en la documentación se hiciera referencia al empleo de cursores, pero en lo práctica no hubiera rastro de ellos. Tras unos minutos de investigación y el comodín de la llamada (gracias Nacho!!) descubrimos que los cursores forward-only, read-only en ADO.NET son los firehose cursors de ADO, que para empezar no son cursores, y por otra parte tampoco apagan fuegos! xD

En realidad, estos 'cursores' son solo un mecanismo para mover de modo rápido datos de un servidor SQL Server al cliente que los ha solicitado. En la práctica, lo que hacen es enviar directamente los datos solicitados por cliente al output buffer del SQL Server. Cuando éste buffer se llena, espera hasta que el cliente pueda recoger estos datos y lo vuelve a llenar de nuevo. Este proceso se repite una y otra vez hasta que el cliente puede recuperar todos los datos.

Como se puede ver, no es el cliente el que va solicitando items como en un cursor tradicional, sino el servidor quien envía todo lo que puede la output buffer. Los bloqueos solo se mantienen mientras el servidor mueve los datos a éste buffer, de modo que no depende de la velocidad de recogida de los datos por parte del cliente, lo que ayuda a mejorar considerablemente el rendimiento y concurrencia. 

En definitiva:

  1. Cuando veamos en la documentación de ADO.NET un cursor forward-only  read-only, no nos llevemos las manos a la cabeza. No son cursores de verdad, y su rendimiento y bloqueos no tienen nada que ver con un cursor ad hoc.
  2. Lo importante no es saber, es tener el teléfono del que sabe xD 
  3. Los aritos de cebolla molan 1024, pero los fingers de queso tiene un mayor Cool Factor(tm).
Posted: 17/11/2006 17:17 por Pablo Alvarez | con 10 comment(s) |
Archivado en: ,
Comparte este post:

Comentarios

Jorge Serrano ha opinado:

Bueno, sobre esto que comentas Pablo y en concreto con el buffer de descarga de datos, van mis dos centavos.

Siempre que doy un curso de ADO.NET pregunto... ¿DataReader es puro conectado o es desconectado?... ante esta pregunta, prometo que en unas horas cuelgo un comentario de como funciona esto y si puedo me hago la "mini demo".

Aviso por adelantado, que esto que comento aquí, es lo que hacía en mis cabañas en el lanzamiento de Visual Studio 2005 en España. :-D

# November 17, 2006 11:55 PM

Jorge Serrano - MVP Visual Developer - Visual Basic ha opinado:

Artículo :: Programación :: ADO.NET ¿Trabaja el objeto DataReader realmente en un ambiente conectado?

# November 18, 2006 7:26 PM

Jorge Serrano - MVP Visual Developer - Visual Basic ha opinado:

Después de leer el comentario de mi compi Pablo Álvarez Doval en su blog acerca de si los DataReader

# November 18, 2006 7:31 PM

Sergio Tarrillo ha opinado:

Holas!

El segundo tip es altamente recomendable :D:

"Lo importante no es saber, es tener el teléfono del que sabe xD".

No recuerdo donde haberlo escuchado *-), pero ahora veo que es de carácter internacional :o!

Saludos,

# November 20, 2006 4:32 PM

Pablo Alvarez ha opinado:

Si no me equivoco es de los grandisimos "Les Luthiers", autores de la no menos aclamada frase "La pereza es la madre de todos los vicios, y como madre hay que respetarla." :)

Jorge, genial tu artículo! (como siempre!)

# November 20, 2006 5:08 PM

Bloggers MSDN Latam ha opinado:

Después de leer el comentario de mi compi Pablo Álvarez Doval en su blog acerca de si los DataReader

# December 19, 2006 11:40 AM

El blog de Jorge ha opinado:

Artículo :: Programación :: ADO.NET ¿Trabaja el objeto DataReader realmente en un ambiente conectado

# February 12, 2008 6:08 PM

Adal ha opinado:

Hola que tal, nuevamente por aqui leyendo tu blog, tus articulos son geniales. Yo trabajo con .Net y SQL Server y siempre he estado en contra de usar cursores, y pensaba que no habia nada mas aberrante que eso, pues si te esfuerzas un poco siempre hay forma de evitarlos. Bueno, decia que pensaba que no habia nada mas aberrante que el uso de cursores, pues bien, hace tiempo descubri que si lo hay; y es el uso de cursores dentro de SQL dinámico.

Saludos desde México!!!!

# April 29, 2009 3:52 PM

Pablo Alvarez ha opinado:

Adal!! Excelente comentario, me lo apunto para mis charlas de SQL Server, ya que Cursores + SQL Dinamico es dificil de superar xD

Por cierto, gracias por tus amables comentarios sobre mis posts :)

Un saludo!!

# June 8, 2009 4:19 PM