Par kolācijām un datu tipiem
Datu tipi char un nchar (tāpat kā varchar un nvarchar), īsi sakot, atšķiras ar to, ka char glabā katru simbolu vienā baitā, kamēr nchar glabā katru simbolu divos baitos. Tas arī nozīmē, ka char var saglabāt mazāk dažādu simbolu kā nchar. Un galu galā- char laukā simboli tiek kodēti izmantojot norādīto kolāciju, kamēr nchar laukā- izmantojot Unicode kodējumu (par to plašāk citreiz).
Apskatīsim šādu vaicājumu:
Select 'Jānis' LatvianCol, N'Jānis' UnicodeColTātad- tiek atgrieztas divas kolonnas- 'LatvianCol' un 'UnicodeCol'. Šajā situācijā redzama atšķirība vaicājumu rezultātos nav. Bet atšķirība ir. Atkal, daudz neiegrimstot detaļās- pirmā kolonnā dati tiek kodēti izmantojot vienu baitu, otrajā kolonnā divus baitus. Un atšķirība ir tādēļ, ka vienā gadījumā teksta lauks ir atzīmēts ar pēdiņām, bet otrā gadījumā, pēdiņām priekšā ir N burts (N'Jānis').
Pārtulkoju vārdu "Karsts" uz arābu valodu (jo ārā patiešām ir ļoti karsts), un ieguvu ilustratīvāku piemēru:
Tātad- viens simbols ir par maz, lai kodētu arābu burtus, tādēļ tiek aizstāti ar '???' simboliem. Šeit būtu daudz ko piebilst un papildināt, bet kā jau minēju- šoreiz galvenā uzmanība uz to, ka ir atšķirība, vai tekstu ieliekam pēdiņās ('Jānis'), vai ieliekam pēdiņās un pieliekam priekšā N burtu (N'Jānis')
Vaicājumu parametri
Lai neatkārtotos, vislabāk būtu, ja būtu vismaz pārskriets pāri rakstam SARG optimizācija.
Kad tas izdarīts, saliekam visu kopā, un apskatām šādu piemēru (Piemēra nolūkos veidojam tabulu):
Create Table dbo.TestTableTātad- ir divas kolonas- "Skaitlis" un "NSkaitlis". Abās tiek glabātas nejaušas skaitliskas vērtības pārvērstas tekstuālā formātā. Vienā gadījumā VarChar kolonnā, otrā gadījumā NVarChar kolonnā. Abām kolonnām ir izveidots indeks.
(
TestTableID int Identity primary key,
Skaitlis VarChar(50),
NSkaitlis NVarChar(50)
)
Go
Set NoCount ON
Declare @i int
Set @i = 0
While @i < 10000
Begin
Insert Into dbo.TestTable(Skaitlis, NSkaitlis)
Values(Cast(Rand()*10000000 as VarChar(50)),
Cast(Rand()*10000000 as NVarChar(50)) );
Set @i = @i + 1;
End
Go
Create Index IX_Skaitlis On dbo.TestTable
(
Skaitlis
)
Go
Create Index IX_MainigsGarums On dbo.TestTable
(
NSkaitlis
)
Un tagad 4 vaicājumi:
Select * From dbo.TestTable Where NSkaitlis = '111' --OKVisos 'OK' gadījumos vaicājuma izpildes plāns būs labs- rezultāts tiks meklēts indeksā, kamēr sliktajā gadījumā, indeks tiks pārlasīts, visas tekstuālās vērtības konvertētas un tikai tad salīdzinātas ar meklējamo tekstu.
Select * From dbo.TestTable Where NSkaitlis = N'111' --OK
Select * From dbo.TestTable Where Skaitlis = '111' --OK
Select * From dbo.TestTable Where Skaitlis = N'111' --Slikti
Pirmajā gadījumā var "zem pārsega" pārkodēt meklējamo '111' uz N'111' (kodēt tos pašus redzamos simbolus izmantojot citu kodu tabulu).
Otrajā un trešajā gadījumā mēs salīdzinām vienādus datu tipus, līdz ar to nekāda datu tipu konvertācija nav vajadzīga.
Pēdējā, sliktajā, gadījumā SQL Server nevar automātiski pārkonvertēt divos baitos kodētu vērtību uz vienā baitā glabātu vērtību, tādēļ nekas cits neatliek, kā konvertēt kolonnas datus uz diviem baitiem. Tas beidzas ar to, ka ir jānolasa pilnīgi visas attiecīgās kolonnas vērtības, katra no tām jākonvertē un jāsalīdzina ar parametru vērtību.
Kopsavilkums
pirmais, ko rakstā gribēju pateikt:
- NChar kolonnu salīdzināt ar NChar parametru ir ļoti labi
- NChar kolonnu salīdzināt ar Char parametru ir labi
- Char kolonnu salīdzināt ar Char parametru ir ļoti labi
- Char kolonnu salīdzināt ar NChar parametru ir slikti
otrais:
Select * From Tabula Where colX = 'vērtība'
nav tas pats, kas
Select * From Tabula Where colX = N'vērtība'
SQL 2012 situācija ir labāka- "Slikti" vairs nebūs tik slikti- būs brīdinājums (Warning), bet netiks pārlasītas visas vērtības.
AtbildētDzēst