Przechowywanie dużej ilości danych w SQL Server

SQL Server posiada kilka mechanizmów umożliwiających przechowywanie dużej ilości danych np. plików graficznych.

FileStream

Pierwszych z nich jest FILESTREAM. Przed pojawieniem się typu FILESTREAM, programiści najczęściej zapisywali pliki sami na dysku a lokalizacje przechowali w bazie danych. Rozwiązanie dobre jednak kłopoty powstały w momencie synchronizacji – co jeśli ktoś usunie jakiś plik z dysku? FILESTREAM to nic innego jak zapisanie pliku w bazie danych. W przeciwieństwie do typu varbinary, FILESTREAM przechowywany jest w osobnym pliku a nie w pliku  tabeli. Zwiększa to wydajność, jednak zwykłe poleca się go dla danych większych niż 1 MB.

Najpierw jednak należy skonfigurować odpowiednio bazę danych. Wszystko można zrobić z poziomu T-SQL jednak w poście pokażę jak to wykonać w SQL Server Management Studio. Najpierw klikamy na bazie danych i przechodzimy do zakładki FIleGroups a następnie dodajemy nowy FileStream (FileStreamTest):

image

Następnie musimy podłączyć utworzoną grupę do konkretnego pliku (folderu). Przechodzimy do zakładki Files i tworzymy nowy plik bazy:

image

Jeśli zajrzymy do utworzonego właśnie folderu zobaczymy plik o rozszerzeniu hdr (filestream.hdr) zawierający metadane, $FSLOG służący jako transaction log, oraz kilka folderów których nazwy stanowią globalne identyfikatory – przechowują one już właściwe dane.

Możemy teraz przejść do utworzenia tabeli. Kod:

create table SampleTable
(
ID  uniqueidentifier not null rowguidcol unique,
DATA varbinary(max) FILESTREAM null
)

Warto zauważyć, że tabela z kolumną FileStream musi zawierać unikalny w skali globalnej (rowguidcol) identyfikator. Tabela została utworzona i możemy przejść do umieszczania danych. W momencie gdy usuwamy dane  FILESTREAM tak naprawdę zostaną one permanentnie usunięte z dysku gdy SQL Server odpali pewien proces czyszczący te dane. Spróbujmy dodać dane z poziomu T-SQL:

DECLARE @SomeData AS VARBINARY(MAX)

 -- zaladowanie danych
SELECT @img = CAST(bulkcolumn AS VARBINARY(MAX))

      FROM OPENROWSET(
            BULK
            'C:\obrazek.jpg',
            SINGLE_BLOB ) AS x

           
INSERT INTO Images (ID, Image)
SELECT NEWID(), @img

Z poziomu c#: (odczyt):


SqlCommand sqlCommand = new SqlCommand();
sqlCommand.Connection = con
sqlCommand.CommandText = "SELECT Image FROM Images " + _

                         "WHERE ID = 'jakis_id'"

byte[] buffer= = sqlCommand.ExecuteScalar();

MemoryStream memoryStream = new MemoryStream(buffer);
Bitmap bitmap=new Bitmap(memoryStream);

Na koniec należy wspomnieć również o konfiguracji dostępu do FILESTREAM:

EXEC sp_configure filestream_access_level, 2
GO
RECONFIGURE
GO

Procedura przyjmuje jako parametry liczby 1,2,3 oznaczające kolejno dostęp wyłącznie za pomocą T-SQL, dostęp za pomocą systemu plików oraz dostęp z użyciem sieci (share).

Oczywiście istnieje wiele sposobów zapisu danych – nie tylko przez użycie tablicy bajtów.

Drugim mechanizmem jest czysty typ VARBINARY – bez atrybutu FILESTREAM. Proces wstawania, selekcji danych jest identyczny jednak parametry wydajnościowe są różne. Generalnie zasada jest prosta – dla małych plików wydajniejszy jest czysty VARBINARY ponieważ nie wiąże się on z dodatkowym czasem poświęconym na zapisywanie pliku w innej strukturze. Dla dużych (>1MB) lepiej używać FILESTREAM.

4 thoughts on “Przechowywanie dużej ilości danych w SQL Server”

  1. Do zdjęć raczej nie – byłaby to metoda dość mało wydajna.
    Jednak do jakiś raportów, które nie są bezpośrednio ściągane (a analizowane itp.) jak najbardziej.

Leave a Reply

Your email address will not be published.