Jacek Jagieła
Language: Polish
Każda aplikacja potrzebuje przechowywać dane, potrzebuje łatwego i szybkiego do nich dostępu. Rozwój aplikacji stawia nowe wyzwania przed baza danych, coraz więcej rzeczy potrzebujemy zapisać i odczytać. Klienci oczekuja szybkiego wyszukiwania, które będzie dawać "dobre" odpowiedzi. Dalsza ekspansja działu marketingu powoduje wprowadzenie obsługi wielu języków. Każdy klient potrzebuje raportów i agregat do właściwych wniosków w obsługiwanej przez nasz SaaS firmie. Architekt wybrał silnik bazy, który uchodzi za niezniszczalny - udźwignie wszystko zawsze i wszędzie. Czy jedna baza danych wystarczy? W którym momencie nastapi katastrofa - jak jej uniknać i jak się z niej podnieść. Zapoznamy się z wykorzystaniem baz danych w projekcie SaaS - od niewielkiej funkcjonalności - do aplikacji działajacej na wszystkich kontynentach w kilkunastu językach. Zobaczymy o czym nie wolno zapomnieć projektujac bazę danych. Czy SaaS dotyczy tylko klienta i jego oczekiwań? A może pojęcie SaaS powinno nam towrzyszyć na każdym etapie projektowania aplikacji?
4Developers 2015: Baza danych w aplikacji typu SaaS - błędy w projektowaniu - Jacek Jagieła
1. Baza danych w aplikacji typu SaaS -
błędy w projektowaniu
jacek.jagiela@gmail.com
2. Agenda
• SaaS?
• Jak to sie zaczeło? Java + Postgres
• Wprowadzamy Oracle
• Klienci w wielu językach
• Wyszukiwarka K2
• Raporty
3. SaaS co to jest?
• Czy to jest tylko aplikacja w Internecie?
• Jakie są główne cechy SaaS?
• Czy portal to już SaaS?
• Systemy pocztowe?
4. SaaS
• Architektura zorientowana na usługi
• Realizuje określoną funkcjonalność
• Wysoka dostępność
• Prosta konfiguracja
• Bezpieczeństwo danych
• Izolacja użytkowników
• Personalizacja
• Infrastruktura servera jest nieistotna dla użytkownika
• Łatwa automatyczna aktualizacja
• Wszyscy korzystają z tej samej wersji
5. Początek
• Mamy aplikację napisaną w Javie
• Oferujemy szkolenia w sieci
• Platforma dla nauczycieli
• Platforma dla uczniów
• Udostępniamy szkolenia
• Można się dzielić rozwiązaniami
• Strony wyświetlana przez jsp
6.
7. Baza danych
• Schemat per klient
• Dodatkowy schemat globalny określający
uprawnienia, konfiguracje schematów
klientów, sposób logowania się do aplikacji,
konfiguracja usług zewnętrznych typu FTP,
EMAIL => GLOBALSCHEMA
8.
9. Wzrost aktywności
• Pierwsze problemy z wydajnością
• Klienci przestają być zadowoleni
• Nie znamy zachowań klientów
• Brak predykcji dotyczącej wykorzystania naszej
aplikacji
• Decyzja Kupujemy Oracle
10. ORACLE
• Jest komercyjny
• Wszyscy wiedzą że jest najlepszy
• Support 24/7
• Najbardziej wydajna baza danych
11. ORACLE – błędny wybór?
• Nie wiemy co jest nie tak z Postgresem
• Nie znamy statystyk z działania naszego systemu
• Co jest źródlem problemów?
• Gdzie jest wąskie gardło?
• Ilu klientów możemy maksymalnie obsłużyć na
tym co mamy?
• Jaki jest Design/Model naszej bazy danych?
• Decyzja o zmianie silnika nie może być
podyktowana tylko narzekaniem klientow
12. Dlaczego to będzie sukces?
• Zatrudnimy konsultantów
• Kupujemy duuuży serwer
• Dużo ramu
• Reforma infrastruktury
• Zrobimy podmiane POSTGRES ORACLE
13. Wdrożenie nowej bazy
• Tworzymy nowe tabele zgodnie ze schematem w
Postgresie
• Zmieniamy procedury
• Wielu developerów Javy - mało czasu
• Architekci od Javy
• Procedury PL/SQL pisane jak w Javie
• Java jest OK wydajna – to baza spowalnia
wszystko
• Wdrożenie Oracle uratuje naszą pozycję na rynku
• Dobry marketing – mamy Oracle
14. Błędy w kolejnych fazach rozwoju
• Dodając nowe klasy w Javie – dodajemy nowe
tabele i kolumny
• Baza staje się
śmietnikiem
zduplikowanych
danych
15. Języki
• Nasza aplikacja wychodzi na świat
• Chcemy aby każdy czytał w swoim języku
• Wdrażając obsługę języków mamy 20 klientów
• Strategia – klient to jeden schemat – jak wdrożyć
języki
• Mamy moduł rozszerzający formatki i formularze
• Chcemy aby klient mógł definiować swoje
określenia
16. Architektura Języków
• Wprowadzamy Listę Wartości LV
• Zdefiniowaliśmy na początek 120 000 określeń
wymagających tłumaczeń
• Mamy ORACLE – wrzucimy to w tabele
• Tworzymy tabele LV, LABELS
18. CREATE TABLE LABELS
( "NKEYNAMEID" NUMBER(10,0) NOT NULL,
"NLVID" NUMBER(10,0) NOT NULL,
"SLANGUAGE" VARCHAR2(4 BYTE) DEFAULT 'EN',
"SLABEL" VARCHAR2(510 BYTE) NOT NULL,
"SUPPERLABEL" VARCHAR2(510 BYTE) NOT NULL
);
19. Dylemat gdzie ja trzymać?
• GLOBALSCHEMA – dodawanie nazw
specyficznych dla użytkownika skomplikuje
zapytania
• SCHEMAT klienta – będzie dużo duplikatów
20. PERFORMANCE ponad wszystko
• Dodajemy do schematu użytkownika
• Przy 20 klientach:
– 120 000 x 20 = 2 400 000 rekordów
– 10 – 15% nazwy zdefiniowane przez użytkownika
– Zamiast 100 000 identycznych nazw mamy
2 000 000 z duplikatami
22. Po roku lub dwóch
• Wzrost klientów do 400
• LABELS/klient 140 000
• 140 000 x 400 = 56 000 000
• 40 000 000 duplikatów
• Za dużo danych w różnych tabelach i
schematach – nie mieści się w CACHE
23. Jak przetrwać
• Baza danych zawsze powinna zwracać w
języku domyślnym
• Tłumaczenia powinny być „Usługą”.
• To część UI – jedna z jego warstw
• LABELS mogą być przechowywane w tabeli w
bazie operacyjnej
• Obsługa powinna być w pamięci
24. Wyszukiwarka
• Nasz SaaS – portal szkoleniowy
• Integruje nauczycieli różnych dziedzin
• Pozwala wymieniać informacje między uczniami
• Abonament dla uczniów
• Nie udostępniamy wszystkich danych na zewnątrz
• Chcemy mieć wszystkie dane ONLINE
• GOOGLE nie ma wstępu
26. Wybieramy K2
• Server K2 – indekser + prezenter danych
• Broker K2 – zarządza serwerami K2
• Zasilanie K2 – XML files
• Użycie K2 – komunikacja z Brokerem na porcie
TCP
27. Co potrzebne do użycia K2
• Serwer (farma serverów) z K2
• Globalna wyszukiwarka dla wszystkich
• Jedna kolejka zasilania K2
• Zasilamy danymi z bazy
• Kolejka – tabela w bazie danych
29. Problemy
• Kolejne obciążenie bazy danych nie
zdefiniowane jako usługa
• Jedna tabela tworzy kolejkę – to rośnie w
nieskończoność
• Złamanie założenia dostępności Online
• K2 źle wyszukuje kontekstowo
• Szybkie wyszukiwanie zwraca złe wyniki
30. Rozszerzamy wyszukiwanie
• Nasz przyjaciel Oracle ma wyszukiwanie
kontekstowe – Domain Index
• Wprowadzimy dwie formatki:
– Quick search – oracle
– Advance search – K2
• W aplikacji zdecydujemy z czego będziemy
korzystać w zależności od kontekstu
użytkownika
31. If ........ {
k2call
} else if (.... ) {
sql = Select name,
FROM trainings
WHERE
contains(describe, ......) > 0
}
32. Błędy
• Wszystko ONLINE!!
• Jeśli coś jest w bazie operacyjnej to powinno
być dostępne
• Brak Design wyszukiwarki
• Rozproszenie wyszukiwania w wielu miejscach
• Brak MOM
33.
34. Raporty
• Dane muszą być ONLINE
• Raporty definiowane przez użytkowników
• Dowolne agregaty
• Raporty wyklikiwane – NIE SQL!!!!
35. Wprowadzamy Typy Raportów
• Sztywna lista pól
• Określamy zbiór tabel dla każdego typu
• Sztywne powiązania (JOIN)
• Agregaty zdefiniowane przez programistów
• Warunki wynikajace z uprawnień w systemie
• Warunki wprowadzane przez użytkowników
36.
37. Tłumaczenia w raportach
SELECT
FIRST_NAME,
(SELECT NVL(H_LB.SLABEL,H_L.SLOVVALUE) FROM LOV H_L, LABELS H_LB WHERE
H_L.NKEYNAMEID=H_LB.NKEYNAMEID(+) AND H_LB.SLANGUAGE(+)='UK' AND
H_L.NLOVID=JLO1.NLOVID) AS JLO1_NLOVID_6971,
(SELECT NVL(H_LB.SLABEL,H_K.SKEYNAME) FROM KEYNAMES H_K, LABELS H_LB WHERE
H_K.NKEYNAMEID=H_LB.NKEYNAMEID(+) AND H_LB.SLANGUAGE(+)='UK' AND
H_K.NKEYNAMEID=ST1.NKEYNAMEID) AS ST1_NKEYNAMEID,
(SELECT NVL(H_LB.SLABEL,H_K.SKEYNAME) FROM KEYNAMES H_K, LABELS H_LB WHERE
H_K.NKEYNAMEID=H_LB.NKEYNAMEID(+) AND H_LB.SLANGUAGE(+)='UK' AND
H_K.NKEYNAMEID=ST2.NKEYNAMEID) AS ST2_NKEYNAMEID,
(SELECT NVL(H_LB.SLABEL,H_K.SKEYNAME) FROM KEYNAMES H_K, LABELS H_LB WHERE
H_K.NKEYNAMEID=H_LB.NKEYNAMEID(+) AND H_LB.SLANGUAGE(+)='UK' AND
H_K.NKEYNAMEID=ST3.NKEYNAMEID) AS ST3_NKEYNAMEID,
(SELECT NVL(H_LB.SLABEL,H_K.SKEYNAME) FROM KEYNAMES H_K, LABELS H_LB WHERE
H_K.NKEYNAMEID=H_LB.NKEYNAMEID(+) AND H_LB.SLANGUAGE(+)='UK' AND
H_K.NKEYNAMEID=ST4.NKEYNAMEID) AS ST4_NKEYNAMEID
....
FROM
.....
38. Agregaty
• Nie używamy funkcji analitycznych Oracle –
ciężko je wyklikać
• Piszemy własne funkcje analityczne
• Duże ilości danych zbieramy w View
• Klient może wiele razy odpowiadać na test w
raportach interesuje nas tylko ostatnia
odpowiedź
• Kwerendy w raportach optymalizujemy pod
raporty
39. create or replace
FUNCTION AgregateF (nCustomerID in number, nquestionid in number) return
varchar2
as
v_STEXT VARCHAR2(4000);
BEGIN
SELECT SFREETEXT INTO v_STEXT
FROM VIEW_F_MC TQF0
WHERE answerid =
(SELECT MAX (answerid)
FROM VIEW_F_MC
WHERE questionid = nquestionid
AND applicationid = nApplicationID)
AND questionid = nquestionid
AND applicationid = nApplicationID;
return (v_SFREETEXT);
END;
40. CREATE OR REPLACE VIEW "VIEW_F_MC" AS
SELECT /*+ FIRST_ROWS */
doc.applicationid,
gfd.ndocumentid,
gfan.nanswerid,
gfan.nquestionid,
gfan.sfreetext,
gfan.dDateAnswer
FROM
document doc
INNER JOIN gf_document gfd
ON doc.nobjectid = gfd.ndocumentid
AND doc.vobjecttype = 'STRUCTURED'
INNER JOIN gf_form gff
ON gff.nformid = gfd.nformid
INNER JOIN gf_assignedquestion gfaq
ON gfaq.nformid = gff.nformid
INNER JOIN gf_answer gfan
ON gfan.nassignedquestionid = gfaq.nassignedquestionid
AND gfan.ndocumentid = gfd.ndocumentid;
41. SELECT
C1.LASTNAME AS C1_LASTNAME,
C1.FIRSTNAME AS C1_FIRSTNAME,
A1.CREATIONDATE AS A1_CREATIONDATE,
F_AGGR_MC(A1.nApplicationId, 5, 459) AS A1_16683_26489_EXP,
F_AGGR_MC(A1.nApplicationId, 5, 460) AS A1_16683_26490_EXP,
F_AGGR_MC(A1.nApplicationId, 5, 461) AS A1_16683_26491_EXP,
F_AGGR_MC(A1.nApplicationId, 5, 462) AS A1_16683_26492_EXP,
F_AGGR_FT(A1.nApplicationId, 5) AS A1_5_414_16683_OTHER,
' ' AS A1_16683_TOTAL
FROM
APPLICATION A1,
CANDIDATE C1,
TRAININGSLIST DJJ1
WHERE
A1.NCANDIDATEID=C1.NCANDIDATEID
AND A1.NOPENINGID=DJJ1.NOPENINGID
AND rownum < 64001
ORDER BY
C1_SLASTNAME,A1_DCREATIONDATE
43. Wnioski
• Baza danych w SaaS to usługa, która powinna
być modelowana
• Monitoring bazy od kwerend przez CPU,
pamiec, Load
• Predykcja wykorzystania przez klientów
• Nie można mieć dobrej Bazy Operacyjnej i
Bazy Raportowej w jednym silniku
• Wyszukiwarka to też baza danych tylko
wspierająca Bazę Operacyjną