Tengo una mesa como esta:
CREATE TABLE Updates
(
UpdateId INT NOT NULL IDENTITY(1,1) PRIMARY KEY,
ObjectId INT NOT NULL
)
Esencialmente, el seguimiento de las actualizaciones de los objetos con una identificación creciente
El consumidor de esta tabla seleccionará un trozo de 100 ID de objetos distintos, ordenados por UpdateId
y a partir de un específico UpdateId
. Esencialmente, hacer un seguimiento de dónde se quedó y luego consultar cualquier actualización.
He encontrado que esto sea un problema de optimización interesante porque sólo he sido capaz de generar un plan de consulta óptimo máximo escribiendo consultas que suceden a hacer lo que quiero, debido a los índices, pero no garantizo lo que quiero:
SELECT DISTINCT TOP 100 ObjectId
FROM Updates
WHERE UpdateId > @fromUpdateId
Donde @fromUpdateId
es un parámetro de procedimiento almacenado.
Con un plan de:
SELECT <- TOP <- Hash match (flow distinct, 100 rows touched) <- Index seek
Debido a la búsqueda en el UpdateId
índice que se está utilizando, los resultados ya son agradables y están ordenados de la ID de actualización más baja a la más alta como quiero. Y esto genera un plan de flujo distinto , que es lo que quiero. Pero el orden obviamente no es un comportamiento garantizado, por lo que no quiero usarlo.
Este truco también da como resultado el mismo plan de consulta (aunque con un TOP redundante):
WITH ids AS
(
SELECT ObjectId
FROM Updates
WHERE UpdateId > @fromUpdateId
ORDER BY UpdateId OFFSET 0 ROWS
)
SELECT DISTINCT TOP 100 ObjectId FROM ids
Sin embargo, no estoy seguro (y sospecho que no) si esto realmente garantiza el pedido.
Una consulta que esperaba que SQL Server fuera lo suficientemente inteligente como para simplificar fue esta, pero termina generando un plan de consulta muy malo:
SELECT TOP 100 ObjectId
FROM Updates
WHERE UpdateId > @fromUpdateId
GROUP BY ObjectId
ORDER BY MIN(UpdateId)
Con un plan de:
SELECT <- Top N Sort <- Hash Match aggregate (50,000+ rows touched) <- Index Seek
Estoy tratando de encontrar una manera de generar un plan óptimo con una búsqueda de índice UpdateId
y un flujo distinto para eliminar los duplicados ObjectId
. ¿Algunas ideas?
Datos de muestra si lo desea. Los objetos rara vez tendrán más de una actualización, y casi nunca deberían tener más de una dentro de un conjunto de 100 filas, por lo que busco un flujo distinto , a menos que haya algo mejor que no conozca. Sin embargo, no hay garantía de que una sola ObjectId
no tenga más de 100 filas en la tabla. La tabla tiene más de 1,000,000 de filas y se espera que crezca rápidamente.
Suponga que el usuario de esto tiene otra forma de encontrar el siguiente apropiado @fromUpdateId
. No es necesario devolverlo en esta consulta.
fuente