Perché l'uso delle chiavi di stringa è generalmente considerato una cattiva idea?


24

Questo mi ha infastidito per un po '. Il più delle volte, quando si tratta di archiviare dati in strutture come hashtable, programmatori, libri e articoli insistono sul fatto che l'indicizzazione di elementi in dette strutture in base a valori String sia considerata una cattiva pratica. Eppure, finora, non ho trovato un'unica fonte per spiegare anche PERCHÉ è considerata una cattiva pratica. Dipende dal linguaggio di programmazione? Sul quadro sottostante? Sulla realizzazione?

Prendi due semplici esempi, se aiuta:

Una tabella simile a SQL in cui le righe sono indicizzate da una chiave primaria String.

Un dizionario .NET in cui le chiavi sono stringhe.


9
Avere chiavi di stringa non è una cattiva idea in generale. Sospetto che quelle dichiarazioni siano state fatte in un contesto in cui è disponibile un tipo di chiave migliore. Ho sempre dizionari .net con chiavi di stringa. Puoi fare alcuni esempi di questa affermazione?
Codici InChaos

3
Di solito vuoi chiavi primarie che non cambiano nel corso della vita di un oggetto / riga. Quindi, ad esempio, usernamepoiché la chiave primaria di una userstabella non è probabilmente la migliore idea e preferiresti un ID di incremento automatico. Ma questa usernameè una stringa è solo casuale, essere una proprietà mutabile è il problema principale
CodesInChaos

In un database, considera come indicizzare le stringhe anziché gli interi.

@CodesInChaos Vorrei ricordare dove ho trovato la maggior parte dei casi, ma per ora posso incollare il bit che mi ha ricordato il problema. Veniva da una presentazione GDC di Valve che discuteva dei dialoghi di gioco e memorizzava fatti sul mondo in coppie <chiave = stringa, valore = oggetto>.

2
Le stringhe vanno bene. Semplicemente non stringhe "magiche". Quindi, quando usi una tabella hash, assicurati di non avere stringhe nude nel tuo codice. Dovresti evitare valori di testo di grandi dimensioni come chiavi perché non funzionano bene, ma nella maggior parte delle situazioni del mondo reale una breve stringa di testo è veloce quanto un intero (non sono enormi database). Puoi anche usare chiavi alternative, ad esempio, la chiave primaria è un numero ma c'è anche un 'slug' o una stringa univoca che è anche unica.
ipaul

Risposte:


17

Tutto ha a che fare con le due cose in sostanza:

1) La velocità di ricerca (in cui i numeri interi, ad esempio, vanno molto meglio)

2) La dimensione degli indici (dove esploderebbero gli indici di stringa)

Ora tutto dipende dalle tue esigenze e dalle dimensioni del set di dati. Se una tabella o una raccolta contiene 10-20 elementi, il tipo di chiave è irrilevante. Sarà molto veloce anche con una chiave di stringa.

PS Potrebbe non essere correlato alla tua domanda, ma le guide sono considerate dannose anche per le chiavi del database (Guid 16 byte contro intero 4 byte). Su grandi volumi di dati, le guide rallentano la ricerca.


Non sempre: sono possibili GUID incrementali. Gli indici saranno ancora più grandi, ma la penalità di ricerca non sarà altrettanto negativa.
Sam

7
In realtà stanno bene. È necessario esaminare la relazione tra il tempo di I / O del disco temporale e il confronto dei valori in memoria. Poiché i tempi di accesso al disco travolgono il confronto della memoria, l'unica cosa che conta davvero nell'analisi delle prestazioni del database è IO. Che la chiave sia un GUID, una stringa o un numero intero non è realmente critico. La dimensione dell'indice influisce su quanti valori di indice rientrano in una pagina, ma se la chiave è un int di 4 byte (che potrebbe non essere abbastanza grande e non può essere generato dal client) o un valore di 16 byte non è un problema significativo. In alcuni database l'ID riga può avere una dimensione di 16 byte.
ipaul

9

C'è un altro problema nell'uso delle stringhe come chiavi o, più precisamente, nell'uso dei valori letterali delle stringhe come chiavi, mettendo da parte le ragioni di pura efficienza / efficienza. Errori di battitura. Se usi letterali stringa come chiavi in ​​un dizionario, ti stai preparando per una brutta sorpresa quando si "ReceiverId"diventa a "RecieverId". Imposta costanti per memorizzare i valori chiave e riutilizzarli ogni volta che accedi al dizionario.

Triviale e ovvio, si può dire, eppure un numero incredibile di esempi di codice .NET sul Web utilizza letterali stringa, propagando questa pratica dubbia. ASP.NET con tutte le Sessioni, ViewStates e QueryParams sparsi nella base di codice è particolarmente colpevole qui.


IMHO non banale. Ho anche visto casi in cui ci sono chiavi "1"e "1 "nella stessa tabella.
pswg

Diventa ancora più divertente quando aggiungi la distinzione tra maiuscole e minuscole nel mix. Ho visto un sacco di persone, incluso me stesso inciampare direttamente in quella.
Tony Hopkinson,

Ancora meglio dell'uso delle costanti, almeno in C #, usa invece le espressioni. In questo modo puoi generare le tue stringhe dai nomi di metodi / proprietà, ecc. In modo che le tue ricerche di stringhe diventino sicure e compatibili con i refactor.
GoatInTheMachine

4

Ci sono molti compromessi qui. In realtà uso spesso le chiavi di stringa, ma spesso includo chiavi secondarie surrogate per i join (ovviamente sarebbe il contrario se usassi MySQL). Ci sono casi in cui non lo faccio comunque.

Innanzitutto sono un fan di dichiarare le chiavi naturali come chiave primaria in cui il db può gestire bene (PostgreSQL per esempio). Questo aiuta con la normalizzazione e rende più chiara la progettazione del database. I tasti surrogati facilitano l'unione.

Esistono due motivi per cui di solito aggiungo chiavi surrogate:

  1. Non è sempre chiaro quale sia una chiave naturale. A volte questi devono essere cambiati. La modifica di una chiave composita naturale quando viene utilizzata per join e integrità referenziale è complicata e soggetta a errori.

  2. Unire le prestazioni su tasti compositi è problematico e una volta che percorri il percorso chiave naturale, rimani bloccato lì.

Nei casi in cui una chiave naturale è di definizione, singola colonna e testo, tuttavia, di solito mi unisco alla chiave di stringa. La mia ragione per farlo è che questo spesso evita di partecipare alla ricerca. L'uso più comune è fornire una corretta progettazione db attorno al caso d'uso di tipi di enum. Nella maggior parte dei casi, questi non richiedono il join aggiuntivo per le query di routine. Quindi, in questo caso, le chiavi di stringa come chiavi di join hanno perfettamente senso.

Ad esempio in LedgerSMB, archiviamo le categorizzazioni degli account. Questi sono identificati dal riferimento di stringa e alcuni altri dati sono memorizzati con il riferimento di stringa che viene utilizzato per applicare le regole relative alle combinazioni di categorizzazioni che possono influenzare un account. L'unica volta in cui è necessaria la logica è quando si salva un set di categorizzazioni, quindi ci uniamo alla chiave di stringa.

Per quanto riguarda il motivo per cui il valore predefinito sarebbe chiavi intere, non credo sia solo una questione di dimensioni dell'indice. Un grosso problema è la gestione delle chiavi. Poiché la chiave è arbitraria e potresti avere a che fare con milioni di record, devi avere un modo per generare stringhe uniche. Ci sono casi in cui le persone usano UUID per questo, ma c'è una possibilità diversa da zero di collisione UUID e dove sono archiviati miliardi di record, questa possibilità diventa abbastanza alta che si potrebbe effettivamente vedere mentre la possibilità di collisione con tipi interi incrementati è zero per definizione.


Non è diverso da zero se riesci a riportare a zero il tipo intero. Per un tipo senza segno a 32 bit, che è solo 4G di distanza, che è inquietantemente vicino con "miliardi di record" ...
Donal Fellows

Se hai un db che puoi dire "errore piuttosto che avvolgente" è zero. In ogni caso è più facile gestire la possibilità di collisione con numeri interi incrementali che con valori pseudocasuali.
Chris Travers,

1

Esistono una serie di potenziali problemi con l'utilizzo delle stringhe come chiavi, specialmente quando si tratta di tabelle di tipo sql. Come accennato da @bunny, gli indici per le tue tabelle saranno più grandi, ma penso più significativamente, qualsiasi relazione di chiave esterna con la tabella coinvolgerà ENTRAMBE le tabelle per contenere la stringa rispetto a un identificatore più leggero (intero) . Se scopri che ci sono ancora più tabelle con riferimenti al primo, le chiavi di stringa verranno proliferate in tutto il database.


1

Non è una cattiva idea in sé e per sé, di solito è con il senno di poi 20/20 un cattivo compromesso progettuale. La flessibilità e la gamma di stringhe rispetto al costo e alla complessità aggiuntivi.

Se il numero intero fa un intervallo di lavoro saggio e la maggior parte dell'elaborazione costosa non ha bisogno di sapere cosa rappresenta il numero intero, usarne uno.


0

In qualche modo hai recuperato i dati sbagliati da un Hashtable.

Intendevi "DaytimeTelephone" o "EveningTelephone"?

o

Intendevi 1234567 o 1234576?

Mentre i numeri sono probabilmente più efficienti per la macchina , ogni volta che le cose vanno male (e lo fanno), spetta a te e te capire cosa è successo e, a quel punto, quel risparmio di pochi byte di spazio di archiviazione e pochi micro (nano?) - secondi di elaborazione perdono chiarezza ogni volta.


1
E così finisci con un elenco di costanti, usando il nome della costante nel tuo codice per rappresentare il numero magico ... Java entra in soccorso per sottrarlo ancora di più e lasciarti solo con il nome e avere l'ordinale mappatura invisibile.
jwenting

-1

Un sacco di compromessi e nessuna risposta giusta. Molti programmatori non prenderebbero mai in considerazione l'uso delle chiavi di stringa nel database perché non sono a conoscenza dell'hash e del funzionamento di un database. Le chiavi di stringa purché siano estremamente stabili o insignificanti (surrogati), sono una buona scelta di progettazione in molte circostanze.


2
Questa risposta non aggiunge nulla che non sia già stato detto nelle altre risposte, che lo dica meglio.
Martijn Pieters,

-2

la chiave stringa avrà senso, quando si tratta di una tabella di ricerca con circa 10-100 record di stringhe brevi; i dati correlati sono più leggibili + ad es. rilevamento delle modifiche (ID numerico / guida vs. stringa ad es. "Amministratore"); tra l'altro, il database di appartenenza ASP.NET utilizza le chiavi di stringa per AspNetRoles.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.