Esta é uma pergunta derivada da ordem de classificação especificada na chave primária, mas a classificação é executada em SELECT .
@Catcall diz isso sobre o assunto da ordem de armazenamento (índice clusterizado) e da ordem de saída
Muitas pessoas acreditam que um índice em cluster garante uma ordem de classificação na saída. Mas não é isso que faz; garante uma ordem de armazenamento em disco. Veja, por exemplo, esta postagem no blog .
Eu li o post de Hugo Kornelis e entendo que um índice não garante que o servidor sql leia os registros em uma ordem específica. No entanto, tenho dificuldade em aceitar que não posso assumir isso para o meu cenário?
CREATE TABLE [dbo].[SensorValues](
[DeviceId] [int] NOT NULL,
[SensorId] [int] NOT NULL,
[SensorValue] [int] NOT NULL,
[Date] [int] NOT NULL,
CONSTRAINT [PK_SensorValues] PRIMARY KEY CLUSTERED
(
[DeviceId] ASC,
[SensorId] ASC,
[Date] DESC
) WITH (
FILLFACTOR=75,
DATA_COMPRESSION = PAGE,
PAD_INDEX = OFF,
STATISTICS_NORECOMPUTE = OFF,
SORT_IN_TEMPDB = OFF,
IGNORE_DUP_KEY = OFF,
ONLINE = OFF,
ALLOW_ROW_LOCKS = ON,
ALLOW_PAGE_LOCKS = ON)
ON [MyPartitioningScheme]([Date])
Minha consulta original foi esta:
SELECT TOP 1 SensorValue
FROM SensorValues
WHERE SensorId = 53
AND DeviceId = 3819
AND Date < 1339225010
ORDER BY Date DESC
Mas sugiro que eu também possa usar este (leia abaixo para minha explicação):
SELECT TOP 1 SensorValue
FROM SensorValues
WHERE SensorId = 53
AND DeviceId = 3819
AND Date < 1339225010
Como você pode ver, minhas linhas da tabela são pequenas (16 bytes) e eu tenho apenas um índice, um cluster. No meu cenário, a tabela consiste em 100.000.000 registros neste momento (e isso provavelmente aumentará dez vezes).
Quando o servidor de banco de dados consulta essa tabela, ele tem duas maneiras de encontrar minhas linhas: ele procura a chave primária e, assim, lê e retorna meus valores em desc. Data ou deve fazer uma verificação completa da tabela. Minha conclusão é que uma verificação completa da tabela em todos esses registros será muito lenta e, portanto, o servidor de banco de dados sempre buscará a tabela por meio de sua chave primária, retornando os valores classificados porDate DESC
ORDER BY
lá, então você sabe que pode confiar nele. Veja o # 3 aquiORDER BY
cláusula é um grande desempenho para mim (leia a outra pergunta para obter mais informações). Eu tenho uma solução que funciona por enquanto, mas ela não funciona quando e se meu tráfego aumentar.ORDER BY
cláusula na sua consulta. Isso é verdade para SQL Server , Oracle , MySQL e qualquer outro RDBMS que você possa imaginar. Tente qualquer outra coisa e você está se preparando para um copo surpresa de FAIL.Respostas:
Deixe-me tentar explicar por que você não deve fazer isso, por que você nunca deve assumir que um produto SQL retornará um conjunto de resultados em uma ordem específica, a menos que você o especifique, quaisquer que sejam os índices - em cluster ou não em cluster, árvores B ou Árvores R ou árvores Kd ou árvores fractal ou quaisquer outros índices exóticos que um DBMS esteja usando.
Sua consulta original informa ao DBMS para pesquisar na
SensorValues
tabela, encontrar linhas que correspondam às 3 condições, ordenar essas linhas porDate
descida, manter apenas a primeira linha daquelas e - finalmente - selecionar e retornar apenas aSensorValue
coluna.Essas são ordens muito específicas que você forneceu ao DBMS e o resultado provavelmente será o mesmo sempre que você executar a consulta (há uma chance de que não ocorra, se você tiver mais de uma linha que corresponda às condições e as mesmas máximo,
Date
mas diferente,SensorValue
mas vamos supor, durante o restante da conversa, que essas linhas não existam na sua tabela).O DBMS precisa fazer isso, para executar esta consulta, da maneira exata como a descrevi acima? Não, claro que não, e você sabe disso. Pode não ler a tabela, mas ler de um índice. Ou pode usar dois índices se achar melhor (mais rápido). Ou três. Ou pode usar um resultado em cache (não o SQL Server, mas outros resultados da consulta ao cache do DBMS). Ou pode usar a execução paralela uma vez e não na próxima vez em que é executada. Ou ... (adicione qualquer outro recurso que afeta a execução e os planos de execução).
O que é garantido é que ele retornará exatamente o mesmo resultado, toda vez que você o executar - desde que nenhuma linha seja inserida, excluída ou atualizada.
Agora vamos ver o que sua sugestão diz:
Essa consulta informa ao DBMS para pesquisar na
SensorValues
tabela, encontrar linhas que correspondam às 3 condições,ordená-las pornão se importar com o pedido, manter apenas uma linha e, finalmente, selecionar e retornar apenas aDate
descendente,SensorValue
coluna.Portanto, basicamente diz o mesmo que o primeiro, exceto que diz que você deseja apenas um resultado que corresponda às condições e não se importa com qual deles .
Agora, podemos supor que ele sempre dará o mesmo resultado por causa do índice clusterizado?
- Se ele usar esse índice clusterizado toda vez, sim.
Mas será que vai usá-lo?
- Não.
Por que não?
- Porque pode. O otimizador de consulta é livre para escolher um caminho de execução sempre que executar uma instrução. Qualquer que seja o caminho que achar adequado naquele momento para essa afirmação.
Mas o uso do índice clusterizado não é a melhor / mais rápida maneira de obter resultados?
- Não, nem sempre. Pode ser a primeira vez que você executa a consulta. Na segunda vez, ele pode usar um resultado em cache (se o DBMS tiver esse recurso, não o SQL Server * ). A milésima vez que o resultado pode ter sido removido do cache e outro resultado pode existir lá. Digamos que você executou esta consulta imediatamente antes:
e o resultado em cache (da consulta acima) é outro, diferente, que ainda corresponde às suas condições, mas não é o primeiro em seu pedido (desejado). E você disse ao DBMS para não se importar com o pedido.
OK, então apenas o cache pode afetar isso?
- Não, muitas outras coisas também.
*: O SQL Server não armazena em cache os resultados da consulta, mas o Enterprise Edition possui um recurso de Verificação avançada , que é semelhante à medida que você pode obter resultados diferentes devido a consultas simultâneas. Não tenho certeza exatamente quando isso entra em ação. (thnx @Martin Smith pela dica.)
Espero que você esteja convencido de que nunca deve confiar que uma consulta SQL retornará resultados em uma ordem específica, a menos que você o especifique. E nunca use
TOP (n)
semORDER BY
, a menos que você queira apenas n linhas no resultado e não se importe com quais são retornadas.fonte