Mam zamiar stworzyć tabelę z dwoma polami - ID
jako BIGINT
i IPAddress
jako albo varchar(45)
albo varbinary(16)
. Chodzi o to, aby przechowywać wszystkie unikalne adresy IP i ID
zamiast tego używać referencji IP address
w innych tabelach.
Zasadniczo zamierzam utworzyć procedurę składowaną, która zwraca wartość ID
dla podanego IP address
lub (jeśli adres nie został znaleziony) wstawić adres i zwrócić wygenerowany ID
.
Oczekuję, że będę mieć wiele rekordów (nie mogę dokładnie powiedzieć, ile), ale potrzebuję, aby powyższa procedura przechowywana została wykonana tak szybko, jak to możliwe. Zastanawiam się więc, jak przechowywać rzeczywisty adres IP - w formacie tekstowym lub bajtowym. Które będzie lepsze?
Napisałem już SQL CLR
funkcje do przekształcania bajtów adresu IP na ciąg znaków i odwrotnie, więc transformacja nie stanowi problemu (praca z oboma IPv4
i IPv6
).
Myślę, że muszę utworzyć indeks, aby zoptymalizować wyszukiwanie, ale nie jestem pewien, czy powinienem dołączyć IP address
pole do indeksu klastrowanego, czy utworzyć osobny indeks i przy jakim typie wyszukiwanie będzie szybsze?
IPv4
, chyba zmieniłbym adresINT
i używał pola jako klucza indeksu. Ale ponieważIPv6
muszę użyć dwóchBIGINT
pól i wolę przechowywać wartość w jednym polu - wydaje mi się to bardziej naturalne.Odpowiedzi:
Ponieważ „tekst” tutaj odnosi się do
VARCHAR(45)
„bajtów”VARBINARY(16)
, powiedziałbym: ani .Biorąc pod uwagę następujące informacje (z artykułu Wikipedii na temat IPv6 ):
Zacznę od użycia 8
VARBINARY(2)
pól do reprezentowania 8 grup. Pola dla grup 5-8 powinny być takie,NULL
jak będą używane tylko dla adresów IPv6. Pola dla grup 1–4 powinny byćNOT NULL
takie, jakie będą używane zarówno dla adresów IPv4, jak i IPv6.Utrzymując każdej niezależnej grupy (w przeciwieństwie do ich łączenia się albo
VARCHAR(45)
alboVARBINARY(16)
albo nawet dwaBIGINT
pola) masz dwie główne korzyści:IF
/IIF
/CASE
stwierdzenia, aby to ułatwić.ROW COMPRESSION
alboPAGE COMPRESSION
. Ponieważ oba typy KOMPRESJI pozwolą na pola, które0x00
zajmą 0 bajtów, wszystkie te grupy zer nie będą cię teraz nic kosztować. Z drugiej strony, jeśli zapisałeś przykładowy adres z góry (w cytacie z Wikipedii), wówczas 3 zestawy wszystkich zer w środku zajmowałyby ich pełną ilość miejsca (chyba że robiłeś toVARCHAR(45)
i poszedłeś ze zmniejszoną notacją , ale może to nie działać dobrze w przypadku indeksowania i wymaga specjalnego analizowania w celu zrekonstruowania go do pełnego formatu, więc załóżmy, że nie jest to opcja ;-).JEŚLI musisz przejąć Sieć, utwórz
TINYINT
pole dla tego, co nazywa się, um,[Network]
:-)Aby uzyskać więcej informacji na temat wartości sieci, oto informacje z innego artykułu w Wikipedii na temat adresu IPv6 :
Do indeksowania powiedziałbym, że utwórz indeks nieklastrowany na 8 polach grupy i ewentualnie polu sieci, jeśli zdecydujesz się go dołączyć.
Wynik końcowy powinien wyglądać następująco:
Uwagi:
BIGINT
pola ID, ale czy naprawdę spodziewasz się przechwycić ponad 4 294 967 295 unikalnych wartości? Jeśli tak, to po prostu zmień pole na DUŻE, a następnie możesz nawet zmienić wartość początkową na 0. Ale w przeciwnym razie lepiej jest użyć INT i zacząć od wartości minimalnej, abyś mógł korzystać z całego zakresu tego typu danych .SELECT *
zwróciło pola w oczekiwanej kolejności. Ale indeks ma ich wzrost , od 1 do 8, ponieważ w ten sposób są wypełniane.Przykładem (niedokończona) kolumny obliczanej do reprezentowania wartości w formie tekstowej jest:
Test:
Wynik:
źródło
VARDECIMAL
zakończonych,VARBINARY
ponieważDATA_COMPRESSION
nie jest dostępne?BINARY(16)
;-). Czy możesz podać mi przykład z zakresem początkowym / końcowym i co najmniej dwoma odzyskanymi wierszami, jednym ważnym i co najmniej jednym nieprawidłowym? Możliwe, że VARbinary skraca niektóre wartości.Mniejsze zawsze będą szybsze. Przy mniejszych wartościach możesz zmieścić więcej z nich na jednej stronie, dlatego mniej IO, potencjalnie płytsze B-Drzewa itp.
Oczywiście wszystkie inne rzeczy (koszty ogólne tłumaczenia, czytelność, kompatybilność, obciążenie procesora, indeksowalność itp.) Są równe.
źródło