Recentemente, expliquei aos colegas a importância de ter uma coluna para classificar os dados em uma tabela do banco de dados, se necessário, por exemplo, para dados ordenados cronologicamente. Isso se mostrou um pouco difícil, porque eles poderiam simplesmente executar novamente sua consulta aparentemente sem parar e sempre retornaria o mesmo conjunto de linhas na mesma ordem.
Já notei isso antes e tudo o que realmente pude fazer é insistir que eles confiem em mim e não simplesmente assumir que uma tabela de banco de dados se comportará como um arquivo CSV ou Excel tradicional.
Por exemplo, executando a consulta (PostgreSQL)
create table mytable (
id INTEGER PRIMARY KEY,
data TEXT
);
INSERT INTO mytable VALUES
(0, 'a'),
(1, 'b'),
(2, 'c'),
(3, 'd'),
(4, 'e'),
(5, 'f'),
(6, 'g'),
(7, 'h'),
(8, 'i'),
(9, 'j');
criará uma tabela com uma ordem conceitual clara. Selecionar esses mesmos dados da maneira mais simples seria:
SELECT * FROM mytable;
Sempre me fornece os seguintes resultados:
id | data
----+------
0 | a
1 | b
2 | c
3 | d
4 | e
5 | f
6 | g
7 | h
8 | i
9 | j
(10 rows)
Eu posso fazer isso repetidamente e sempre retornará para mim os mesmos dados na mesma ordem. No entanto, eu sei que essa ordem implícita pode ser quebrada, já a vi antes, principalmente em grandes conjuntos de dados, nos quais algum valor aleatório aparentemente será jogado no local "errado" quando selecionado. Mas me ocorreu que não sei como isso acontece ou como reproduzi-lo. Acho difícil obter resultados no Google porque a consulta de pesquisa tende a retornar apenas uma ajuda geral na classificação dos conjuntos de resultados.
Então, minhas perguntas são essencialmente estas:
Como posso demonstrar de forma demonstrável e concreta que a ordem de retorno de linhas de uma consulta sem uma
ORDER BY
instrução não é confiável, de preferência causando e mostrando uma discriminação da ordem implícita, mesmo quando a tabela em questão não é atualizada ou editada ?Faz alguma diferença se os dados são inseridos apenas uma vez em massa e nunca mais são atualizados?
Eu preferiria uma resposta baseada no postgres, já que essa é a que eu estou mais familiarizada, mas estou mais interessada na própria teoria.
order by
cláusula às consultas deles? Eles estão tentando economizar no armazenamento do código-fonte? desgaste do teclado? tempo necessário para digitar a temida cláusula?Respostas:
Eu vejo três maneiras de tentar convencê-los:
Deixe-os tentar a mesma consulta, mas com tabela maior (mais número de linhas) ou quando a tabela estiver sendo atualizada entre as execuções. Ou novas linhas são inseridas e algumas antigas são excluídas. Ou um índice é adicionado ou removido entre as execuções. Ou a tabela é aspirada (no Postgres). Ou os índices são reconstruídos (no SQL Server). Ou a tabela é alterada de cluster para um heap. Ou o serviço de banco de dados é reiniciado.
Você pode sugerir que eles provem que execuções diferentes retornarão a mesma ordem. Eles podem provar isso? Eles podem fornecer uma série de testes que comprovam que qualquer consulta fornecerá o resultado na mesma ordem, não importa quantas vezes seja executada?
Forneça a documentação de vários DBMS nesse assunto. Por exemplo:
PostgreSQL :
SQL Server :
Oracle :
fonte
ORDER BY
, que garanta o pedido, não importa como a tabela vai mudar ? Por que não adicionar um cofre, que não faz mal?Esta é a história do cisne negro mais uma vez. Se você ainda não viu um, isso não significa que eles não existem. Felizmente, no seu caso, isso não levará a outra crise financeira mundial, simplesmente a alguns clientes insatisfeitos.
A documentação do Postgres diz isso explicitamente:
"O sistema" neste caso compreende o próprio daemon do postgres (incluindo a implementação de seus métodos de acesso a dados e o otimizador de consultas), o sistema operacional subjacente, o layout lógico e físico do armazenamento do banco de dados, possivelmente até os caches da CPU. Como você, como usuário do banco de dados, não tem controle sobre essa pilha, não deve confiar que ela continuará a se comportar para sempre da maneira como se comporta neste minuto.
Seus colegas estão cometendo a falácia generalizada apressada . Para refutar seu argumento, basta mostrar que sua suposição está errada apenas uma vez, por exemplo, com este dbfiddle .
fonte
Considere o exemplo a seguir, onde temos três tabelas relacionadas. Pedidos, Usuários e Detalhes do Pedido. OrderDetails está vinculado a chaves estrangeiras na tabela Orders e na tabela Users. Essa é essencialmente uma configuração muito típica para bancos de dados relacionais; indiscutivelmente todo o propósito de um DBMS relacional .
Aqui, estamos consultando a tabela OrderDetails em que o UserID é 15:
A saída da consulta é semelhante a:
Como você pode ver, a ordem das linhas de saída não corresponde à ordem das linhas na tabela OrderDetails.
Adicionar um explícito
ORDER BY
garante que as linhas sejam retornadas ao cliente na ordem desejada:Se a ordem de linhas é imperativo, e seus engenheiros sabem que a ordem é imperativo, eles devem sempre apenas quer usar um
ORDER BY
comunicado, uma vez que pode custar-lhes a sua designação, se houve uma falha relacionada à ordem incorreta.Um segundo exemplo, talvez mais instrutivo, usando a
OrderDetails
tabela acima, em que não estamos juntando nenhuma outra tabela, mas com um requisito simples de encontrar linhas que correspondam ao Código do Pedido e ao Código do Usuário, vemos o problema.Criaremos um índice para dar suporte à consulta, como você provavelmente faria na vida real se o desempenho for de alguma forma importante (quando não é?).
Aqui está a consulta:
E os resultados:
A adição de uma
ORDER BY
cláusula garantirá definitivamente que também obtemos a classificação correta aqui.Esses modelos são apenas exemplos simples, onde não é garantido que as linhas estejam "em ordem" sem uma
ORDER BY
declaração explícita . Existem muitos outros exemplos como esse e, como o código do mecanismo DBMS muda com bastante frequência, o comportamento específico pode mudar com o tempo.fonte
Como um exemplo prático, no Postgres, a ordem atualmente muda quando você atualiza uma linha:
Não acho que as regras dessa ordem implícita existente estejam documentadas em nenhum lugar, estejam definitivamente sujeitas a alterações sem aviso prévio e, definitivamente, não sejam portáveis nos mecanismos de banco de dados.
fonte
não exatamente uma demonstração, mas muito tempo para comentar.
Em tabelas grandes, alguns bancos de dados fazem varreduras paralelas intercaladas:
Se duas consultas desejarem varrer a mesma tabela e chegarem quase ao mesmo tempo, a primeira poderá fazer parte da tabela quando a segunda iniciar.
A segunda consulta pode receber registros começando no meio da tabela (quando a primeira consulta está sendo concluída) e, em seguida, receber os registros desde o início da tabela.
fonte
Crie um índice clusterizado que tenha a ordem "incorreta". Por exemplo, cluster em
ID DESC
. Isso geralmente gera a ordem inversa (embora isso também não seja garantido).fonte