ResultSet: Recuperação de valores de coluna por índice contra recuperar pelo rótulo
-
06-07-2019 - |
Pergunta
Ao usar JDBC, eu muitas vezes deparamos com construções como
ResultSet rs = ps.executeQuery();
while (rs.next()) {
int id = rs.getInt(1);
// Some other actions
}
Perguntei-me (e autores de código também) porque não usar rótulos para recuperar valores de coluna:
int id = rs.getInt("CUSTOMER_ID");
A melhor explicação que eu ouvi é algo sobre o desempenho. Mas, na verdade, faz o processamento extremamente rápido? Eu não acredito que sim, embora eu nunca ter realizado medições. Mesmo se recuperando pela gravadora seria um pouco mais lento, no entanto, proporcionar uma melhor legibilidade e flexibilidade, na minha opinião.
Então alguém poderia me dar uma boa explicação de evitar para recuperar valores de coluna por índice de coluna em vez de rótulo de coluna? Quais são prós e contras de ambas as abordagens (talvez, relativas a certos DBMS)?
Solução
Você deve usar rótulos de cordas por padrão.
Pros:
- Independência da ordem da coluna
- Melhor legibilidade / manutenção
Contras:
- Você não tem controle sobre os nomes das colunas (acesso através de procedimentos armazenados)
O que você prefere?
ints?
int i = 1;
customerId = resultSet.getInt (i ++);
customerName = ResultSet.getString (i ++);
CustomerAddress = ResultSet.getString (i ++);
ou cordas?
customerId = resultSet.getInt ( "customer_id");
customerName = ResultSet.getString ( "customer_name");
CustomerAddress = ResultSet.getString ( "customer_address");
E se há uma nova coluna inserida na posição 1? Qual o código que você prefere? Ou se a ordem das colunas é alterado, qual versão do código que você precisa mudar em tudo?
É por isso que você deve usar rótulos de cordas por padrão.
Outras dicas
Atenção: Eu estou indo para obter bombástica aqui, porque isto me deixa louco
.99% * das vezes, é um micro-otimização ridículo que as pessoas têm uma vaga ideia torna as coisas 'melhor'. Isso ignora completamente o fato de que, a menos que você está em um loop extremamente apertado e ocupado ao longo de milhões de resultados SQL o tempo todo , que é esperançosamente rara, você nunca vai notar. Para todos que não está fazendo isso, o custo de tempo desenvolvedor maintaing, atualização e correção de bugs na indexação coluna são muito maiores do que o custo incremental de hardware para o seu infinitamente pior, desempenho da aplicação.
Não otimizações de código como este no. Código para a pessoa mantê-la. Em seguida, observar, medir, analisar e otimizar. Observe novamente, medir novamente, analisar novamente, e otimizam novamente.
Optimization é praticamente o último passo no desenvolvimento, não o primeiro.
* A figura é composta.
A resposta foi aceite, nada-a-menos, aqui estão algumas informações adicionais e experiência pessoal que eu não vi ainda apresentadas.
Use os nomes das colunas (constantes e não literais é o preferido) em geral e, se possível. Isto é tanto mais clara, é mais fácil de manter, e futuras alterações são menos propensos a quebrar o código.
Há, no entanto, um uso para índices de coluna. Em alguns casos, estes são mais rápidos, mas não suficientemente que este deve substituir as razões acima para nomes *. Estes são muito valioso no desenvolvimento de ferramentas e métodos gerais lidar com ResultSet
s. Finalmente, um índice pode ser necessária porque a coluna não tem um nome (como um agregado sem nome) ou existem nomes duplicados por isso não há maneira fácil de fazer referência ambos.
* Nota que eu escrevi alguns drivers JDBC e olhou para dentro algumas fontes abertas um e internamente esses índices uso de colunas para referenciar as colunas de resultados. Em todos os casos com quem trabalhei, o condutor interno primeira mapeia um nome da coluna para um índice. Assim, você pode ver facilmente que o nome da coluna, em todos os casos, seria sempre levar mais tempo. Isto pode não ser verdade pois embora todos os drivers.
A partir da documentação java:
A interface ResultSet fornece métodos getter (getBoolean, getLong, e assim sucessivamente) para a recuperação de valores de coluna a partir da linha corrente. Os valores podem ser recuperados usando o número do índice da coluna ou o nome da coluna. Em geral, utilizando o índice de coluna será mais eficiente. As colunas são numeradas a partir de 1. Para o máximo de portabilidade, colunas conjunto de resultados dentro de cada linha deve ser lido da esquerda para a direita a fim, e cada coluna deve ser lido apenas uma vez.
É claro que cada método (chamado ou indexada) tem o seu lugar. Concordo que colunas nomeadas deve ser o padrão. No entanto, nos casos em que são necessários um grande número de loops, e onde a instrução SELECT é definido e mantidos na mesma seção do código (ou classe), os índices devem estar ok - é aconselhável para listar as colunas que estão sendo selecionadas, e não apenas "SELECT * FROM ...", uma vez que qualquer mudança mesa vai quebrar o código.
Claro, usando nomes de coluna aumenta a legibilidade e facilita a manutenção. Mas o uso de nomes de colunas tem um efeito colateral. Como você sabe, SQL permite que vários nomes de coluna com o mesmo nome, não há nenhuma garantia de que o nome da coluna que você digitou no método getter de resultSet realmente aponta para o nome da coluna que pretende acesso. Em teoria, usando números de índice em vez de nomes de coluna é preffered, mas reduz a legibilidade ...
Graças
Eu não acho que usando o desempenho etiquetas impactos por muito. Mas há outra razão para não usar String
s. Ou int
s, para essa matéria.
Considere o uso de constantes. Usando uma constante int
torna o código mais legível, mas também menos propensos a ter erros.
Além de ser mais legível, a constante também impede você de fazer typo de nos nomes de rótulo - o compilador irá lançar um erro se o fizer. E qualquer valor IDE nada vai buscá-lo. Este não é o caso, se você usar String
s ou ints
.
Eu fiz algumas desempenho profiling sobre este assunto exato em um banco de dados Oracle. Em nosso código, temos um ResultSet com inúmeras colums e um enorme número de linhas. Dos 20 segundos (!) O pedido leva para executar método oracle.jdbc.driver.ScrollableResultSet.findColumn (String name) leva cerca de 4 segundos.
Obviamente há algo de errado com o design geral, mas usando índices em vez dos nomes de coluna provavelmente levaria este 4 segundos de distância.
Você pode ter o melhor de ambos! A velocidade do uso de índices com a manutenção e segurança do uso de nomes de coluna.
Primeiro -. A menos que você está looping através de um conjunto de resultados apenas usar nomes de coluna
-
Defina um conjunto de variáveis ??inteiras, um para cada coluna que você vai acessar. Os nomes das variáveis ??podem incluir o nome da coluna: por exemplo, iLast_Name.
-
Antes do laço conjunto de resultados iteração através da coluna de metadados e definir o valor de cada variável número inteiro para o índice do nome da coluna correspondente da coluna. Se o índice de coluna 'Last_Name' é 3, em seguida, definir o valor de 'iLast_Name' para 3.
-
No loop conjunto de resultados usar os nomes de variáveis ??inteiro nos métodos GET / SET. O nome da variável é uma pista visual para o desenvolvedor / mantenedor quanto ao nome da coluna real que está sendo acessada, mas o valor é o índice da coluna e vai dar o melhor desempenho.
. NOTA: o mapeamento inicial (isto é, o nome da coluna para o mapeamento de índice) é feito apenas uma vez antes de o ciclo, em vez de para cada ficha e coluna no loop
O driver JDBC cuida para a coluna para o índice do look-up. Então, se você extrair valores pelo nome da coluna cada vez que o motorista faz um look-up (geralmente no mapa de hash) para verificar o índice correspondente para o nome da coluna.
Eu concordo com respostas anteriores que o desempenho não é algo que pode nos forçar para selecionar qualquer uma das abordagens. Seria bom considerar as seguintes coisas em vez disso:
- Código legibilidade:. Para cada desenvolvedor de ler as etiquetas de código têm muito mais sentido do que os índices
- Manutenção: pensar a consulta SQL ea forma como ela é mantida. O que é mais provável de acontecer no seu caso depois da fixação melhorar consulta SQL / / refatoração: alterar a ordem das colunas extraídos ou alterar os nomes das colunas de resultados. Parece para mim que alterar a ordem das colunas extraídos (como os resultados de inclusão / exclusão de novas colunas no conjunto de resultados) tem maior probabilidade de acontecer.
- encapsulamento: apesar da maneira que você escolher tentar isolar o código onde você executar a consulta SQL e conjunto de resultados de análise no mesmo componente e fazer apenas este componente ciente sobre os nomes das colunas e seu mapeamento para os índices (se você decidiu usá-los).
Usando o índice é uma tentativa de otimização.
O tempo poupado por isso é desperdiçado pelo esforço extra que leva o desenvolvedor de olhar para cima os dados necessários para verificar se o seu código irá funcionar corretamente após as alterações.
Eu acho que é a nossa built-in instinto de usar números em vez de texto.
Além do olhar-se no mapa para etiquetas Ela também leva a uma criação de Cordas extra. Mas isso vai acontecer na pilha, mas ainda cárie um custo com ele.
Tudo depende da escolha individual e até agora eu tenho usado apenas índices: -)
Como é apontado por outros cartazes, eu iria ficar com os nomes das colunas a menos que tenha uma razão muito poderosa para não fazê-lo. O impacto no desempenho é insignificante em comparação com, por exemplo, a otimização da consulta. Neste caso, a manutenção é muito mais importante do que uma pequena Otimização.