Quali sono le principali differenze di prestazioni tra i tipi di dati varchar e nvarchar SQL Server?


236

Sto lavorando su un database per una piccola app web nella mia scuola usando SQL Server 2005.
Vedo un paio di scuole di pensiero sulla questione di varcharvs nvarchar:

  1. Utilizzare a varcharmeno che non si tratti di molti dati internazionalizzati, quindi utilizzare nvarchar.
  2. Usa solo nvarcharper tutto.

Sto cominciando a vedere i meriti della vista 2. So che nvarchar occupa il doppio dello spazio, ma questo non è necessariamente un grosso problema poiché memorizzerà i dati solo per alcune centinaia di studenti. Per me sembra che sarebbe più facile non preoccuparsene e permettere a tutto di usare nvarchar. O c'è qualcosa che mi manca?


domanda simile qui: stackoverflow.com/questions/312170/... EDIT dalle dorfier: che è interessante notare è venuto a esattamente alla conclusione opposta.
Booji Boy,

6
fare riferimento a un thread molto più ampio che è giunto alla conclusione opposta. stackoverflow.com/questions/312170/...
dkretz

2
Jason: Spero che questa non sia una richiesta inappropriata, ma puoi per favore considerare di cambiare la risposta accettata a gbn's . La risposta di Joe Bararone è terribilmente sbagliata per molte ragioni. Il fatto di essere "accettato" induce i principianti a fare scelte sbagliate. Non è necessario e dispendioso "utilizzarlo sempre NVARCHAR" e può avere un impatto molto negativo sulle prestazioni e sui costi / budget dell'hardware. Alcune righe, anche alcune migliaia, non importeranno. Ma i sistemi crescono più rapidamente di quanto le persone si aspettino, quindi l'attuale risposta accettata è un disservizio per la comunità. Grazie.
Solomon Rutzky,

Risposte:


140

Usa sempre nvarchar.

Potresti non aver mai bisogno dei caratteri a doppio byte per la maggior parte delle applicazioni. Tuttavia, se è necessario supportare le lingue a doppio byte e si dispone solo del supporto a byte singolo nello schema del database, è molto costoso tornare indietro e modificarlo in tutta l'applicazione.

Il costo della migrazione di un'applicazione da varchar a nvarchar sarà molto più del piccolo spazio aggiuntivo su disco che utilizzerai nella maggior parte delle applicazioni.


4
è molto più difficile tornare indietro e aggiungere supporto per messaggi / messaggi di testo multilingue, fusi orari, unità di misura e valuta, quindi tutti DEVONO sempre codificarli nella loro applicazione fin dal primo giorno, SEMPRE (anche se è solo sulla tua home page web app)!
KM.

82
Che dire della dimensione dell'indice, dell'utilizzo della memoria ecc. Presumo che usi sempre int quando puoi usare anche tinyint "per ogni evenienza"?
gbn

99
Programmare / programmare sempre un sito multilingue (quando non si ha la minima idea di non averne mai bisogno) è come dire a tutti i giovani adulti che dovrebbero acquistare un grande SUV da 8 posti, a gas che consuma gas per la loro prima auto ... dopo tutto , potrebbero sposarsi un giorno e avere 6 figli,. Preferirei godermi le prestazioni e l'efficienza mentre posso e pagare il prezzo per l'aggiornamento quando / se ne ho bisogno.
EJ Brennan,

4
@cbmeeks: non codifico per ciò che non conosco. Ma se riesci a usarlo senza un notevole calo delle prestazioni, i tuoi database non sono abbastanza grandi per essere importanti ...
gbn

60
Di solito quando le persone iniziano la loro risposta con la parola "Sempre", allora dovresti ignorare tutto ciò che viene dopo. (Notate che ho iniziato questa affermazione con la parola "solitamente" :)
Brandon Moore,

226

Lo spazio su disco non è il problema ... ma lo saranno la memoria e le prestazioni. Raddoppia la lettura della pagina, doppia dimensione dell'indice, strano LIKE e = comportamento costante ecc

Hai bisogno di memorizzare script cinesi ecc? Si o no...

E da MS BOL " Effetti di archiviazione e prestazioni di Unicode "

Modifica :

Una recente domanda SO che evidenzia quanto possano essere negative le prestazioni di nvarchar ...

SQL Server utilizza CPU elevate durante la ricerca all'interno delle stringhe nvarchar


19
+1, se la tua app diventa internazionale, avrai molti altri problemi di cui preoccuparti che una ricerca / sostituzione a nvarchar: testo / messaggi multilingue, fusi orari, unità di misura e valuta
KM.

2
Ma cosa succede se è necessario memorizzare un nome straniero a volte, come José o Bjørn?
Qwertie,

7
@Qwertie: allora usi nvarchar. Quello che non lo fai lo usa inutilmente. Quei 2 nomi rientrano comunque in varchar IIRC
gbn

6
Dire che lo spazio su disco non è un problema non è vero per tutti. Abbiamo ingenuamente utilizzato nvarchar inutilmente in una grande applicazione bancaria con miliardi di record archiviati per molti anni. Con costosi storage basati su SAN con replica, backup e disaster recovery, ciò può effettivamente tradursi in milioni di dollari di costi per nvarchar vs varchar. Per non parlare del forte impatto sulle prestazioni (100%) di dover leggere il doppio del byte dal disco per ogni lettura.
codemonkey

2
@codemonkey, et al: ho fatto il possibile per affrontare il problema dello spazio sprecato in modo olistico nel seguente articolo: Disk Is Cheap! ORLY? (è richiesta la registrazione gratuita). L'articolo ha lo scopo di aiutare a prevenire la situazione in cui si è verificato codemonkey per quanto riguarda l'archiviazione costosa a livello aziendale.
Solomon Rutzky,

59

Sii coerente! L'adesione di un VARCHAR a NVARCHAR ha un grande successo in termini di prestazioni.


115
Se stai effettuando un join sui campi dei caratteri, probabilmente il tuo database presenta problemi peggiori rispetto all'utilizzo di nvarchar o varchar, in generale.
Brandon Moore,

@Thomas Harlan Un test semplice mi dimostra che non v'è alcuna differenza tangibile tra l'adesione nvarcharal varcharvs conversione nvarcharper varchare unirsi a varchar. A meno che, naturalmente, non intendessi essere coerente nei tipi di dati di colonna, non nell'unione.
ajeh,

1
@ajeh e Thomas: 1) I test "semplici" sono spesso fuorvianti in quanto non coprono variazioni che causano differenze nel comportamento. 2) Se si vede un calo di prestazioni drastico durante la miscelazione VARCHARe NVARCHAR, che dovrebbe essere dovuto alla indicizzazione della VARCHARcolonna insieme al tipo di confronto utilizzato per quella colonna (e quindi l'indice). Tratterò questo argomento in dettaglio nel seguente post di blog: Impatto sugli indici durante la miscelazione di tipi VARCHAR e NVARCHAR .
Solomon Rutzky,

44

nvarchar avrà un notevole sovraccarico di memoria, archiviazione, working set e indicizzazione, quindi se le specifiche indicano che in realtà non sarà mai necessario, non preoccuparti.

Non avrei una regola "sempre nvarchar" dura e veloce perché può essere uno spreco completo in molte situazioni - in particolare ETL da ASCII / EBCDIC o identificatori e colonne di codice che sono spesso chiavi e chiavi esterne.

D'altra parte, ci sono molti casi di colonne, in cui sarei sicuro di porre presto questa domanda e se non avessi una risposta rapida e immediata immediatamente, renderei la colonna nvarchar.


26

Esito ad aggiungere ancora un'altra risposta qui, poiché ce ne sono già alcune, ma alcuni punti devono essere fatti o non sono stati fatti o non sono stati fatti chiaramente.

Primo: Do non usare sempre NVARCHAR. Questo è un atteggiamento / approccio molto pericoloso e spesso costoso. E non è meglio dire " Non usare mai i cursori" poiché a volte sono il mezzo più efficace per risolvere un problema particolare e il modo più comune per fare un WHILEciclo sarà quasi sempre più lento di un cursore fatto correttamente .

L'unica volta che dovresti usare il termine "sempre" è quando consigli di "fare sempre ciò che è meglio per la situazione". È scontato che spesso sia difficile da determinare, specialmente quando si cerca di bilanciare i guadagni a breve termine nei tempi di sviluppo (manager: "abbiamo bisogno di questa funzione - di cui non si conosceva fino a ora - una settimana fa!") Con molto costi di manutenzione a medio termine (manager che inizialmente ha fatto pressione sul team per completare un progetto di 3 mesi in uno sprint di 3 settimane: "perché stiamo riscontrando questi problemi di prestazioni? Come avremmo potuto fare X che non ha flessibilità? Non possiamo permetterci uno sprint o due per risolvere questo problema. Cosa possiamo fare in una settimana in modo da poter tornare ai nostri elementi prioritari? E dobbiamo sicuramente dedicare più tempo alla progettazione in modo che ciò non accada! ").

Secondo: la risposta di @ gbn tocca alcuni punti molto importanti da considerare quando si prendono determinate decisioni sulla modellazione dei dati quando il percorso non è chiaro al 100%. Ma c'è ancora di più da considerare:

  • dimensione dei file di registro delle transazioni
  • tempo impiegato per replicare (se si utilizza la replica)
  • tempo impiegato per ETL (se ETLing)
  • tempo impiegato per spedire i log in un sistema remoto e ripristinarlo (se si utilizza Log Shipping)
  • dimensione dei backup
  • il tempo necessario per completare il backup
  • il tempo necessario per eseguire un ripristino (questo potrebbe essere importante un giorno ;-)
  • dimensione necessaria per tempdb
  • esecuzione dei trigger (per tabelle inserite ed eliminate archiviate in tempdb)
  • prestazioni del controllo delle versioni delle righe (se si utilizza ISOLAMENTO SNAPSHOT, poiché l'archivio versioni è in tempdb)
  • capacità di ottenere nuovo spazio su disco quando il CFO afferma di aver appena speso $ 1 milione in una SAN l'anno scorso e quindi non autorizzerà altri $ 250k per spazio di archiviazione aggiuntivo
  • il tempo necessario per eseguire le operazioni INSERT e UPDATE
  • il tempo necessario per eseguire la manutenzione dell'indice
  • ecc, ecc, ecc.

Sprecare spazio ha un enorme effetto a cascata su tutto il sistema. Ho scritto un articolo andando in dettaglio esplicito su questo argomento: Disk Is Cheap! ORLY? (è richiesta la registrazione gratuita; mi dispiace non controllo tale politica).

Terzo: mentre alcune risposte si incentrano erroneamente sull'aspetto "questa è una piccola app" e alcune suggeriscono correttamente di "utilizzare ciò che è appropriato", nessuna delle risposte ha fornito una vera guida all'OP Un dettaglio importante menzionato nella domanda è che questa è una pagina web per la loro scuola. Grande! Quindi possiamo suggerire che:

  • I campi per i nomi degli studenti e / o delle facoltà dovrebbero essere probabilmenteNVARCHAR poiché, nel tempo, sta diventando sempre più probabile che i nomi di altre culture vengano visualizzati in quei luoghi.
  • Ma per indirizzo e nomi di città? Lo scopo dell'app non è stato dichiarato (sarebbe stato utile) ma supponendo che gli eventuali record di indirizzi riguardino solo una determinata regione geografica (ovvero una singola lingua / cultura), quindi utilizzare VARCHARcon l'apposita pagina di codice (che è determinato dalla Raccolta del campo).
  • Se si memorizzano codici ISO di stato e / o paese (non è necessario archiviare INT/ TINYINTpoiché i codici ISO sono di lunghezza fissa, leggibili dall'uomo e bene, standard :) utilizzare CHAR(2)per codici a due lettere e CHAR(3)se si utilizzano codici a 3 lettere. E considera l'utilizzo di una raccolta binaria come Latin1_General_100_BIN2.
  • Se si memorizzano codici postali (ad esempio codici postali), utilizzare VARCHARpoiché è uno standard internazionale per non utilizzare mai lettere esterne all'AZ. E sì, usi ancora VARCHARanche se memorizzi solo i codici postali statunitensi e non INT poiché i codici postali non sono numeri, sono stringhe e alcuni di essi hanno uno "0" iniziale. E considera l'utilizzo di una raccolta binaria come Latin1_General_100_BIN2.
  • Se si memorizzano indirizzi e-mail e / o URL, utilizzare NVARCHARpoiché entrambi possono ora contenere caratteri Unicode.
  • e così via....

Quarto: ora che hai i NVARCHARdati che occupano il doppio dello spazio necessario per i dati che si adattano perfettamente VARCHAR("si adatta bene" = non si trasforma in "?") E in qualche modo, come per magia, l'applicazione è cresciuta e ora ci sono milioni di record in almeno uno di questi campi in cui la maggior parte delle righe sono ASCII standard ma alcune contengono caratteri Unicode quindi è necessario conservare NVARCHAR, considerare quanto segue:

  1. Se si utilizza SQL Server 2008-2016 RTM e si utilizza Enterprise Edition, oppure se si utilizza SQL Server 2016 SP1 (che ha reso disponibile la compressione dei dati in tutte le edizioni) o più recente, è possibile abilitare la compressione dei dati . La compressione dei dati può (ma non "sempre") comprimere i dati NCHARe i NVARCHARcampi Unicode . I fattori determinanti sono:

    1. NCHAR(1 - 4000)e NVARCHAR(1 - 4000)utilizzare lo schema di compressione standard per Unicode , ma solo a partire da SQL Server 2008 R2, E solo per i dati IN ROW, non OVERFLOW! Questo sembra essere migliore del normale algoritmo di compressione ROW / PAGE.
    2. NVARCHAR(MAX)e XML(e immagino anche VARBINARY(MAX), TEXTe NTEXT) i dati IN ROW (non fuori riga nelle pagine LOB o OVERFLOW) possono almeno essere compressi PAGE, ma non ROW compressi. Naturalmente, la compressione PAGE dipende dalla dimensione del valore in-row: ho testato con VARCHAR (MAX) e ho visto che 6000 righe di caratteri / byte non si comprimerebbero, ma 4000 righe di caratteri / byte sì.
    3. Qualsiasi dato OFF ROW, LOB o OVERLOW = Nessuna compressione per te!
  2. Se si utilizza SQL Server 2005 o 2008-2016 RTM e non su Enterprise Edition, è possibile avere due campi: uno VARCHARe uno NVARCHAR. Ad esempio, supponiamo che tu stia memorizzando URL che sono principalmente tutti caratteri ASCII di base (valori 0 - 127) e quindi adatti VARCHAR, ma a volte hanno caratteri Unicode. Lo schema può includere i seguenti 3 campi:

      ...
      URLa VARCHAR(2048) NULL,
      URLu NVARCHAR(2048) NULL,
      URL AS (ISNULL(CONVERT(NVARCHAR([URLa])), [URLu])),
      CONSTRAINT [CK_TableName_OneUrlMax] CHECK (
                        ([URLa] IS NOT NULL OR [URLu] IS NOT NULL)
                    AND ([URLa] IS NULL OR [URLu] IS NULL))
    );

    In questo modello SCEGLI solo dalla [URL]colonna calcolata. Per l'inserimento e l'aggiornamento, si determina quale campo utilizzare visualizzando se la conversione modifica il valore in ingresso, che deve essere di NVARCHARtipo:

    INSERT INTO TableName (..., URLa, URLu)
    VALUES (...,
            IIF (CONVERT(VARCHAR(2048), @URL) = @URL, @URL, NULL),
            IIF (CONVERT(VARCHAR(2048), @URL) <> @URL, NULL, @URL)
           );
  3. È possibile GZIP in entrata valori VARBINARY(MAX)e quindi decomprimere in uscita:

    • Per SQL Server 2005-2014: è possibile utilizzare SQLCLR. SQL # (una libreria SQLCLR che ho scritto) viene fornito con Util_GZip e Util_GUnzip nella versione gratuita
    • Per SQL Server 2016 e versioni successive: è possibile utilizzare il built-in COMPRESSe le DECOMPRESSfunzioni, che sono anche GZip.
  4. Se si utilizza SQL Server 2017 o versioni successive, è possibile cercare di rendere la tabella un indice Columnstore cluster.

  5. Sebbene questa non sia ancora un'opzione praticabile, SQL Server 2019 introduce il supporto nativo per UTF-8 in VARCHAR/ CHARdatatypes. Al momento ci sono troppi bug per usarlo, ma se sono stati corretti, questa è un'opzione per alcuni scenari. Si prega di consultare il mio post " Supporto nativo UTF-8 in SQL Server 2019: Salvatore o Falso profeta? ", Per un'analisi dettagliata di questa nuova funzionalità.


7
Clap lento Semplicemente stupito che "usa sempre nvarchar" ottenne 140 voti e questo non lo fece. Ottimo lavoro su questo post.
schizoid04,

1
@ schizoid04 Grazie. Per essere onesti, la risposta accettata è stata pubblicata 7 anni prima della mia, quindi c'è molto traffico che ha votato su di essa (e / o vari altri) che non sono mai tornati a rivalutare. Tuttavia, fornisce un solido contrappunto alla teoria della "saggezza della folla" che guida i forum basati sul voto. C'è troppa disinformazione là fuori. Ad esempio, questo su DBA.SE. L'altra risposta, accettata prima che io inserissi la mia, è "corretta" dalla più stretta delle definizioni, fuorviante e contiene informazioni che confutano nella mia, eppure supera ancora la mia.
Solomon Rutzky,

22

Per la tua applicazione, nvarchar va bene perché le dimensioni del database sono piccole. Dire "usa sempre nvarchar" è un'enorme semplificazione. Se non ti viene richiesto di memorizzare cose come Kanji o altri personaggi folli, usa VARCHAR, utilizzerà molto meno spazio. Il mio predecessore nel mio attuale lavoro ha progettato qualcosa usando NVARCHAR quando non era necessario. Di recente l'abbiamo passato a VARCHAR e abbiamo salvato 15 GB solo su quella tabella (è stato fortemente scritto). Inoltre, se hai un indice su quella tabella e vuoi includere quella colonna o creare un indice composito, hai appena ingrandito le dimensioni del tuo file indice.

Sii solo riflessivo nella tua decisione; nello sviluppo di SQL e nelle definizioni dei dati sembra che raramente ci sia una "risposta predefinita" (oltre a evitare i cursori a tutti i costi, ovviamente).


10

Poiché l'applicazione è di piccole dimensioni, l'utilizzo di nvarchar su varchar non è sostanzialmente rilevante e si risparmiano potenziali mal di testa lungo la strada se si ha la necessità di archiviare dati unicode.


8

Parlando in generale; Inizia con il tipo di dati più costoso che presenta i vincoli minimi. Mettilo in produzione . Se le prestazioni iniziano a rappresentare un problema, scopri cosa viene effettivamente archiviato in quelle nvarcharcolonne. C'è qualche personaggio lì dentro che non si adatterebbe varchar? In caso contrario, passa a varchar. Non provare a pre-ottimizzare prima di sapere dove si trova il dolore. La mia ipotesi è che la scelta tra nvarchar / varchar non è ciò che rallenterà la tua applicazione in un futuro prevedibile. Ci saranno altre parti dell'applicazione in cui l'ottimizzazione delle prestazioni vi darà molto più scoppio per i Bucks .


7

Negli ultimi anni tutti i nostri progetti hanno usato NVARCHAR per tutto, dal momento che tutti questi progetti sono multilingue. I dati importati da fonti esterne (ad es. Un file ASCII, ecc.) Vengono convertiti in Unicode prima di essere inseriti nel database.

Devo ancora riscontrare problemi relativi alle prestazioni dagli indici più grandi, ecc. Gli indici utilizzano più memoria, ma la memoria è economica.

Sia che tu usi le stored procedure o costruisca SQL al volo, assicurati che tutte le costanti di stringa abbiano il prefisso N (ad es. SET @foo = N'Hello world. ';) In modo che anche la costante sia Unicode. Ciò evita qualsiasi conversione del tipo di stringa in fase di esecuzione.

YMMV.


4
Probabilmente non hai diverse centinaia di milioni di record nelle tabelle con cui stai lavorando. Sono d'accordo che per la maggior parte delle app il default su nvarchar va bene, ma non tutto.
Brandon Moore,

7

Posso parlare per esperienza su questo, attenzione nvarchar. A meno che non sia assolutamente necessario, questo tipo di campo dati distrugge le prestazioni su database più grandi. Ho ereditato un database che stava danneggiando in termini di prestazioni e spazio. Siamo riusciti a ridurre le dimensioni di un database di 30 GB del 70%! Ci sono state alcune altre modifiche apportate per aiutare con le prestazioni, ma sono sicuro che anche questo ha varcharcontribuito in modo significativo. Se il tuo database ha il potenziale per aumentare le tabelle a oltre un milione di record, stai alla larga da nvarchartutti i costi.


4

Mi occupo spesso di questa domanda al lavoro:

  • Feed FTP di inventario e prezzi - Le descrizioni degli articoli e altro testo erano in nvarchar quando varchar funzionava bene. La conversione di questi in varchar ha ridotto le dimensioni del file quasi a metà e ha davvero aiutato con i caricamenti.

  • Lo scenario sopra ha funzionato bene fino a quando qualcuno non ha inserito un carattere speciale nella descrizione dell'oggetto (forse un marchio, non ricordo)

Continuo a non usare nvarchar ogni volta su varchar. Se c'è qualche dubbio o potenziale per personaggi speciali, uso nvarchar. Trovo di usare varchar principalmente quando controllo il 100% di ciò che sta popolando il campo.


3

Perché, in tutta questa discussione, non è stato menzionato UTF-8? Essere in grado di memorizzare l'intero arco di caratteri unicode non significa che si debba allocare sempre due byte per carattere (o "punto di codice" per usare il termine UNICODE). Tutta ASCII è UTF-8. SQL Server verifica i campi VARCHAR () che il testo sia ASCII rigoroso (ovvero il byte zero bit zero)? Spero di no.

Se poi desideri archiviare unicode e desideri la compatibilità con vecchie applicazioni solo ASCII, penserei che usare VARCHAR () e UTF-8 sarebbe il proiettile magico: usa solo più spazio quando è necessario.

Per quelli che non conoscono UTF-8, potrei raccomandare un primer .


2
Quello che stai suggerendo potrebbe funzionare per alcune applicazioni, ma devi anche considerare l'impatto di un livello di codifica aggiuntivo sul modo in cui il testo SQL viene elaborato. In particolare, verranno eseguite le regole di confronto, ricerca e corrispondenza dei motivi. E se i report vengono eseguiti sul database, gli strumenti di report standard non interpereranno correttamente i caratteri multi-byte. E le importazioni e le esportazioni all'ingrosso possono essere effettuate. Penso che, a lungo termine, questo schema possa rappresentare più un problema di quanto non valga la pena.
Jeffrey L Whitledge,

1
Non è possibile memorizzare UTF-8 nelle colonne VARCHAR. MSSQL convertirà sempre i tuoi dati UTF-8 nelle regole di confronto delle colonne. Se confondi le regole di confronto (come tentare di memorizzare CP1252 in Latin_1) la conversione non funzionerà e ti ritroverai con byte extra nei tuoi dati. Può sembrare che funzioni correttamente quando converti latin_1 in UTF-8 (sul lato app) e poi di nuovo su latin_1 (lato db) ma è solo un'illusione. Puoi eseguire la conversione automatica del DB nelle regole di confronto delle colonne utilizzando i freetds e impostando il protocollo su un valore inferiore a 7, ma perdi la possibilità di interrogare nvarchar.
Chugadie,

1
@chugadie e Tevya: questa risposta è un po 'priva di senso. SQL Server utilizza solo UCS-2 / UTF-16 per archiviare i dati Unicode (ovvero XML e Ntipi prefissati). Non puoi scegliere di usare UTF-8. Inoltre, le codifiche Unicode (UTF-8, UCS-2 / UTF-16 e UTF-32) non possono essere applicate ai campi VARCHAR.
Solomon Rutzky,

2

Ci saranno casi eccezionali in cui vorrai limitare deliberatamente il tipo di dati per assicurarti che non contenga caratteri di un determinato set. Ad esempio, ho avuto uno scenario in cui avevo bisogno di memorizzare il nome di dominio in un database. Al momento l'internazionalizzazione per i nomi di dominio non era affidabile, quindi era meglio limitare l'input a livello di base e aiutare a evitare potenziali problemi.


1

Se si utilizza NVARCHARsolo perché una procedura memorizzata dal sistema lo richiede, l'occorrenza più frequente è inspiegabilmente sp_executesqle l'SQL dinamico è molto lungo, si sarebbe meglio dal punto di vista delle prestazioni facendo tutte le manipolazioni delle stringhe (concatenazione, sostituzione ecc.) Per VARCHARpoi convertire il risultato finale NVARCHARe lo inserisce nel parametro proc. Quindi no, non usare sempre NVARCHAR!

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.