2009-07-07 8 views
8

Tengo un delimma interesante. Tengo una consulta muy costosa que implica realizar varios análisis completos de tablas y uniones costosas, así como llamar a un UDF escalar que calcula algunos datos geoespaciales.Usando una tabla de caché en SQLServer, ¿estoy loco?

El resultado final es un conjunto de resultados que contiene datos que se presentan al usuario. Sin embargo, no puedo devolver todo lo que quiero mostrar al usuario en una sola llamada, porque subdivido el conjunto de resultados original en páginas y simplemente devuelvo una página específica, y también necesito tomar el conjunto de datos original completo, y aplicar el grupo by's y join etc. para calcular datos agregados relacionados.

Para resumir, para vincular todos los datos que necesito a la interfaz de usuario, esta costosa consulta debe llamarse unas 5-6 veces.

Por lo tanto, comencé a pensar acerca de cómo podía calcular esta costosa consulta una vez, y luego cada llamada subsiguiente podría de alguna manera contra un conjunto de resultados en caché.

Me encontré con la idea de resumir la consulta en un procedimiento almacenado que tomaría un CacheID (Guid) como un parámetro que admite valores NULL.

Este sproc insertaría el conjunto de resultados en una tabla de caché utilizando el identificador de caché para identificar de forma única este conjunto de resultados específico.

Esto permite que los sprocs que necesitan trabajar en este conjunto de resultados pasen un cacheID de una consulta anterior y es una declaración SELECT simple para recuperar los datos (con una sola cláusula WHERE en el cacheID).

Luego, utilizando un trabajo SQL periódico, limpie la tabla de caché.

Esto funciona muy bien, y realmente acelera las cosas en la prueba de carga cero. Sin embargo, me preocupa que esta técnica pueda causar un problema bajo carga con cantidades masivas de lecturas y escrituras contra la tabla de caché.

Por lo tanto, en resumen, ¿estoy loco? O esta es una buena idea?

Obviamente, tengo que preocuparme por la contención del bloqueo y la fragmentación del índice, pero ¿hay algo más por lo que preocuparse?

Respuesta

3

Lo he hecho antes, especialmente cuando no tenía el lujo de editar la aplicación. Creo que es un enfoque válido a veces, pero en general es preferible tener un caché/caché distribuido en la aplicación, ya que reduce la carga en el DB y se escala mejor.

Lo difícil de la ingenua solución "solo hazlo en la aplicación", es que muchas veces tienes múltiples aplicaciones interactuando con la base de datos que te pueden poner en un aprieto si no tienes un bus de mensajería de aplicaciones (o algo así memcached), porque puede ser costoso tener un caché por aplicación.

Obviamente, para su problema, la solución ideal es poder hacer la búsqueda de una manera más barata, y no es necesario revolver TODOS los datos solo para obtener la página N. Pero a veces no es posible. Tenga en cuenta que la transmisión de datos desde la base de datos puede ser más económica que la transmisión de datos desde la base de datos a la misma base de datos. Puede presentar un nuevo servicio que es responsable de ejecutar estas consultas largas y luego hacer que su aplicación principal se comunique con el DB a través del servicio.

+0

¿Entonces tendría que canalizar miles de resultados a la aplicación? – FlySwat

+0

Para elaborar, realizo muchas operaciones de SQL con estos datos y solo envío los resultados a la aplicación. Entonces el almacenamiento en caché de la aplicación sería contraproducente. – FlySwat

+0

@FlySwat, creo que la introducción de un intermediario para esto puede valer la pena considerar, no desea enviar su DB a un ajuste cada vez que las personas ejecutan un informe de larga ejecución, tener un servicio en el medio le dará la capacidad de acelere y reduzca la carga en el DB –

1

Tu tempdb podría hincharse como loco bajo carga, así que lo vería. Puede ser más fácil colocar las combinaciones costosas en una vista e indexar la vista que tratar de almacenar en caché la tabla para cada usuario.

+0

Los resultados son muy arbitrarios y se basan en una gran cantidad de parámetros de entrada, por lo que la vista sería enorme. Esta fue mi primera idea también, pero me di cuenta de que para hacerlo la vista necesitaría millones de filas. – FlySwat

+1

@FlySway, millones de filas no es necesariamente tan malo. especialmente si al final del día es mejor distribuir la carga en el DB y, en general, reducirla. –

Cuestiones relacionadas