2010-05-20 11 views
5

¿Se "une" un servidor SQL para preservar cualquier tipo de orden de fila de manera consistente (es decir, el de la tabla de la izquierda o el de la tabla de la derecha)?¿Cómo se conserva el orden de las filas de la tabla temporal cuando se une internamente con otra tabla?

psuedocode:

create table #p (personid bigint); 
foreach (id in personid_list) 
    insert into #p (personid) values (id) 
select id from users inner join #p on users.personid = #p.id 

Supongamos que tengo una lista de identificadores que corresponden a entradas de persona. Cada uno de esos ID puede corresponder a cero o más cuentas de usuario (ya que cada persona puede tener múltiples cuentas).

Para seleccionar rápidamente columnas de la tabla de usuarios, llento una tabla temporal con identificadores de persona, y luego lo integro con la tabla de usuarios.

Estoy buscando una manera eficiente de asegurar que el orden de los resultados en la unión coincida con el orden de los identificadores cuando se insertaron en la tabla temporal, para que la lista de usuarios que se devuelve esté en el mismo orden como la lista de personas tal como fue ingresada.

he considerado las siguientes alternativas:

  1. utilizando "#P combinación interna usuarios", en caso de que la orden de la tabla de la izquierda se conserva
  2. usando "# p dejó unirse a los usuarios donde id no es nulo ", en caso de que una combinación a la izquierda conserve el orden y la unión interna no
  3. usando" create table (rownum int, personid bigint) ", insertando un número de fila incremental a medida que se llena la tabla temporal, por lo que se pueden ordenar los resultados por rownum en la unión
  4. usando un SQL Server equivalente al " orden por orden de la cláusula [tablename] "disponible en DB2

Actualmente estoy usando la opción 3, y funciona ... pero odio la idea de usar una cláusula order by para algo que ya está ordenado. Sólo que no sé si la tabla temporal conserva el orden en el que se insertan las líneas o cómo opera la unión y en qué orden los resultados salen en

EDIT:.

Suponiendo que vaya con la opción 3, entonces hay un campo para ordenar en ... ¿hay alguna forma de la unión que ayude a SQL Server a hacer la menor cantidad de trabajo para mantener el orden? Quiero decir, ¿es lo suficientemente inteligente, por ejemplo, mirar qué campos de la tabla están en la cláusula order by y trabajar primero en esa tabla mientras se hace la unión, para que el orden del conjunto de resultados coincida casi o completamente con el orden de esa tabla, solo en caso de que ya esté en el orden deseado?

Respuesta

3

Los conjuntos de SQL nunca se ordenan a menos que los ordene explícitamente con una cláusula order by.

Haga lo siguiente:

create table #p (personid bigint); 

insert into #p (personid) values (id) 
select id from users 
ORDER BY <something like users.name>; 

select * from #p 
ORDER BY <something like users.name>; 

Tenga en cuenta que mientras que se puede insertar en orden, eso no significa que el selectivo posterior será ordenada, porque conjuntos SQL no se ordenan a menos que les pide explícitamente con un order by cláusula.

escribe:

Para seleccionar rápidamente las columnas de la tabla de usuarios, que pueblan una tabla temporal con los identificadores de persona, entonces combinación interna con la tabla de usuarios.

Tenga en cuenta que en la mayoría de los casos , va a ser más rápido que acaba de seleccionar directamente de users, utilizando un filtro en la lista:

select * form users where users.id in (1, 2, 3, 6, 9, ...); 

usted está probablemente antes de tiempo "optimización" algo que doesn' Necesito optimizar Los RDBMS son (generalmente) escritos para ser eficientes, y probablemente hagan poco trabajo extra para clasificar algo que ya está ordenado por casualidad. Concéntrese en la funcionalidad hasta que tenga una necesidad demostrada de optimizar. (Lo digo como alguien que ha estado gastando los últimos meses casi exclusivamente optimizando SQL en conjuntos de datos muy grandes (~ 500 millones de filas OLTP), porque la mayoría de las veces, eso es cierto.)

+0

Hay miles de identificaciones involucradas en esta operación (que implica resultados de búsqueda), por lo que no puedo concatenar una cadena seleccionada de la forma que mencionaste. Además, no existe la optimización prematura. Estás haciendo que el código se ejecute más rápido o no, o eres demasiado perezoso para mejorarlo o eres lo suficientemente inteligente como para hacerlo. Estoy bien al rellenar la tabla temporal con una instrucción de inserción parametrizable y reutilizable que se puede almacenar en caché y reutilizar. – Triynko

+0

La otra cosa es ... los ID tienen una ORDEN cuando se insertan (ordenados por los componentes del nombre de la persona), pero dicha orden no tiene nada que ver con los ID numéricos y por lo tanto no están en un orden que es obvio para SQL Server, por lo tanto, no puede ordenarlos con "poco trabajo adicional" (tendría que volver a unirse a la tabla de personas y volver a ordenar los componentes del nombre). Todavía creo que mi tercera opción con el uso de una columna de rownum y ordenarla es la mejor manera de preservar un orden aparentemente arbitrario (al menos desde la perspectiva de SQL Server). – Triynko

+0

Otra cosa ... la decisión de usar un bucle para llenar la tabla temporal, en lugar de una cadena de consulta enorme es más por corrección que por rendimiento (aunque la consulta en caché simple funciona mejor y transmite las inserciones una por una), porque con una sola cadena existe el riesgo de que con un conjunto lo suficientemente grande, se alcance un límite para el texto de comando o el lote (por ejemplo, 65536 * tamaño de paquete (4096bytes)?), mientras que no hay límite práctico para la cantidad de veces que puedo emitir insertar instrucción en una tabla temporal antes de eliminarla. – Triynko

Cuestiones relacionadas