In memory OLTP poajwiło się w SQL server wraz z SQL 2014. Ogólnie rzecz biorąc przebudowano zasady przechowywania wierszy ze znanych nam drzew na ciagi dacych umieszczone w pamięci, a co za tym idzie również zupełnie zmieniono niepodważalne do tej pory święte zasady pracy z danymi, jak np. blokowanie rekordów, które tutaj nie występuje, Ładnie opisuje to cały cykl artykułów na MS SQL Tips:
Dwie rzeczy (co najmniej) były tu jednak niepokojące:
1. Czy dane umieszczone w RAM nie uciekną po wyłączeniu SQL?
2. Wiele znanych konstrukcji SQL i elementów SQL nie mogło być używanych z In memory OLTP.
Odpowiedź na pierwsze pytanie stanowi opcja DURABILITY. Ustawienie jej na SCHEMA_AND_DATA powoduje, że transakcje przechodzą w standardowy sposób przez log transakcyjny, a dane i struktura tabeli jest na stałe zapisywana na dysk.
Z drugim problemem było znacznie gorzej. Masz tabelę ale zapomnij o kluczach obcych, indeksie unikalnym, zapytaniach z UNION, OUTER JOIN itp. I oto pojawił się SQL 2016, a wraz z nim:
UNION / OUTER JOIN / SELECT DISTINCT / OR / NOT / EXISTS / TVF (Table Valued Functions) / Triggery …
Dodatkowo poprawiono też Garbage Collector. Odzyzkiwanie pamięci rozpoczyna się już na etapie pojedynczej transakcji, a co minutę specjalny proces dodatkowo zwalnia to, co nie jest już potrzebne.
Podsumowując – chyba w SQL 2014 trochę się pośpieszono z wypuszczeniem „pół produktu”. In memory OLTP w SQL 2016 wygląda na dość normalną w użyciu technologię.
Podczas standardowego uruchomienia bcp a plikiem format pojawiał się komunikat o błędzie:
[Microsoft][SQL Native Client]I/O error while reading BCP format file
Zazwyczaj I/O error oznacza, że pliku nie można odczytać, bo np nie ma go we właściwym katalogu, jest literówka w nazwie, albo plik jest, ale brakuje do niego uprawnień. Jednak tym razem wszystkie te przyczyny nie były prawdziwe.
Składnia pliku formatu wymaga, aby po ostatniej linii nacisnąć enter. Jeśli tej jednej dodatkowej pustej linii w pliku formatu nie ma, to pojawia się błąd I/O error…
Każda z wcześniejszych wersji SQL miała jedną znaczną bolączkę jeśli chodzi o columnstore index. Otóż utworzenie takiego indeksu wiązało się z tym, że tabela stawała się tylko do odczytu. W wersji 2014 problem został trochę osłabiony, bo clustered columnstore index mógł już być aktualizowany. Problem rozwiązano tam w ten sposób, że w momencie utworzenia indeksu wszystkie tradycyjnie zapisane rekordy były przerabiane na columnstore index, ale dodatkowo „za tym indeksem” powstawał dodatkowy obszar, w którym było można dopisywać informacje o modyfikacjach danych. Jeżeli więc dodano nowy rekord, to wisiał on sobie w tej dodatkowej przestrzeni, za indeksem columnstore. Jeśli rekord usunięto to podobnie dokładano taką informację w postaci tradycyjnego rekordu w tym dodatkowym obszarze. A jeśli rekord zmodyfikowano, to informację dokładało się dwa razy: raz jako usunięcie a raz jako dodanie. Ten obszar nosił nazwę delta store i dotyczył tylko indeksu clustrowanego.
W wersji 2016 podobną funkcjonalność dodano do indeksu nieclustrowanego. Ładne porównanie możliwości columnstore indeksu zawiera tabelka ze strony:
Jedną z głownych zalet posaidania takiego indeksu jest obecnie to, że jeżeli z danych ma korzystać zarówno aplikacja transakcyjna OLTP jak i analityczna OLAP, to wcale nie trzeba tworzyć dwóch instancji SQL połączonych przez procesy ETL. Do tej samej tabeli mogą sie odwoływać transakcje OLTP (bo tabela ma nadal kształt zwykłych rekordów), jak i analityczne (bo query optimizer sam dobierze najbardziej efektywny indeks i będzie to prawdopodobnie columnstore index).
Aktualizowalny nieklustrowany columnstore index podobnie jak to było z indeksem clustrowanym posiada oprócz danych zapisanych w kolumnach również delta store do zapamiętywania bieżących modyfikacji danych. Jeśli taka modyfikacja się przytrafi, to w ramach transakcji trzeba będzie zmodyfikować dane z normalnego (rowstore) indeksu oraz dane w delta store indeksu column store. Ale to nie wszystko!
Dane często charakteryzują się specyfinczym „tokiem życia”. Świeżo po wprowadzeniu do tabeli są gorące – „hot”, tzn. mogą podlegać intensywnym zmianom. Ale przychodzi taki moment, kiedy rekord „stygnie” i staje się „cold” i nie jest już często modyfikowany. Może to być rekord księgowy po zamknięciu miesiąca albo zamówienie, które zostało zrealizowane. Od wersji 2016 nonclustered column store indeks może być filtrowany! Wystarczy więc wymyślić filtr, który oddzieli dane hot od tych cold i nawet dellta store nie będzie musiał być zmieniany.
Zastosowanie tych nowych możliwości w SQL 2016 jest nazywane jako: Real-Time Operational Analytics
Bardzo ładnie opowiada o tym główny projektant dla column store indeksów: Sunil Agarwal:
W Azure można zdefiniować pulę baz danych i przypisać jej pewne gwarantowane zasoby DTU (Database Transaction Units). Można posiadać więcej pul i działanie baz w jednej puli nie ma wpływu na działanie baz w drugiej puli. Dzięki temu unikniesz przydzielania zasobów indywidualnie dla każdej bazy danych, a co za tym idzie przeszacowania zasobów.
Database Transaction Unit – DTU
Istnieją miary względne/umowne (np jeden metr) oraz bezwzględne (np kąt prosty). Określając wydajność baz w Azure przyjęto miarę „jednej transakcji”. Wykupując dostęp do bazy określasz jej DTU.
Elastic Database Trasaction Unit – eDTU
Jeżeli baza znajduje się w elastic database pool, to przyznajesz jej pewną ilość eDTU. Nie oznacza to jednak, że baza rzeczywiście konsumuje tą ilość DTU. Baza, tóra nie jest używana pozostawia swoje DTU dla pozostałych baz w puli.
Od lat programiści byli przyzwyczajeni do przygotowania napisów do wyświetlenia w interfejsie użytkownika z wykorzystaniem SPRINT lub SPRINT-o podobnych funkcji. Właściwie taką właśnie funkcją była i jest RAISERROR. Można np. w taki sposób zgłosić informację o usunięciu rekordów:
RAISERROR(’%d records have been deleted from table %s’,10,1,12345,’app_log’)
Oczywiście najczęściej liczba 12345 i napis 'app_log’ byłyby tu postawiane dynamicznie przez wyliczone wcześniej zmienne.
Gorzej, jeśli chciałeś przygotować podobny napis, ale nie wyświetlać go od razu. Właściwie jedyne co pozostawało, to zwykła konkatenacja ze znakiem + i zabawa z CAST lub CONVERT jeżeli trzeba było połączyć napis z liczbą. I wiecie co? W Microsoft też to zauważyli. Od wersji 2016 dostajemy funkcję FORMATMESSAGE. Działa jak wspomniany wcześniej RAISERROR, ale nie wyświetla napisu, tylko go zwraca, więc można jej użyć w zapytaniach, czy funkcjach itp.:
DECLARE @rowsDeletedINT = 12345
DECLARE @message VARCHAR(1000)
SET @message = FORMATMESSAGE(’%d records have been deleted from database %s, @rowsDeleted, DB_NAME())
Zapraszam do zapoznania się z ofertami pracy IBM Katowice i Wrocław. Prezentuję głównie SQL / Oracle / Windows / Development, ale przecież dostępnych stanowisk jest o wiele więcej…. Wypróbuj, zaaplikuj, może niebawem będziemy pracować w jednym teamie?
Masz ochotę w końcu poznać PowersShella, z którym spotykasz się raz po raz w różnych sytuacjach? Denerwuje Cię, że co druga instrukcja w Internecie każe Ci uruchamiać, których nie znasz? Masz już dość wykonywania powtarzalnych czynności podczas, gdy koledzy potrafią to samo zrobić raz dwa z wykorzystaniem Powershella?
Skorzystaj z kursu „Powershell dla administratorów Windows”! Kurs zaczyna się od podstaw i co bardzo ważne – jest po polsku! Codziennie 10 minut poświęcone na naukę na pewno pozwoli Ci w którkim czasie poznać ten język i zacząć samodzielnie pisać własne skrypty.
Skorzystaj z kuponu promocuyjnego „SPRING”, a cena spadnie do 10$. Kupon waży do końca maja. Szczegóły: http://www.kursyonline24.eu/