4Developers 2015: Baza danych w aplikacji typu SaaS - błędy w projektowaniu - Jacek Jagieła

Post on 15-Jul-2015

177 views 2 download

Transcript of 4Developers 2015: Baza danych w aplikacji typu SaaS - błędy w projektowaniu - Jacek Jagieła

Baza danych w aplikacji typu SaaS -błędy w projektowaniu

jacek.jagiela@gmail.com

Agenda

• SaaS?

• Jak to sie zaczeło? Java + Postgres

• Wprowadzamy Oracle

• Klienci w wielu językach

• Wyszukiwarka K2

• Raporty

SaaS co to jest?

• Czy to jest tylko aplikacja w Internecie?

• Jakie są główne cechy SaaS?

• Czy portal to już SaaS?

• Systemy pocztowe?

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

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

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

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

ORACLE

• Jest komercyjny

• Wszyscy wiedzą że jest najlepszy

• Support 24/7

• Najbardziej wydajna baza danych

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

Dlaczego to będzie sukces?

• Zatrudnimy konsultantów

• Kupujemy duuuży serwer

• Dużo ramu

• Reforma infrastruktury

• Zrobimy podmiane POSTGRES ORACLE

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

Błędy w kolejnych fazach rozwoju

• Dodając nowe klasy w Javie – dodajemy nowe tabele i kolumny

• Baza staje się śmietnikiem zduplikowanychdanych

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

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

CREATE TABLE LV

( "NLVID" NUMBER(10,0) NOT NULL ENABLE,

"NKEYNAMEID" NUMBER(10,0),

"LVNAME" VARCHAR2(120 BYTE) NOT NULL ENABLE,

"DISABLED" NUMBER(1,0) DEFAULT 0,

"DUPDATEDATE" DATE,

"UPDATEUSERID" NUMBER(10,0),

"CREATIONUSERID" NUMBER(10,0),

);

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

);

Dylemat gdzie ja trzymać?

• GLOBALSCHEMA – dodawanie nazw specyficznych dla użytkownika skomplikuje zapytania

• SCHEMAT klienta – będzie dużo duplikatów

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

SQL

SELECT...NVL(t.name, l.label) UI_NAME...

FROM...LEFT JOIN LABELS LON L.NLVID = T.NLVID

...WHERE

L.LANG = UK

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

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

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

Obieg dokumentów

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

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

Zasilanie K2

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

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

If ........ {

k2call

} else if (.... ) {

sql = Select name,

FROM trainings

WHERE

contains(describe, ......) > 0

}

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

Raporty

• Dane muszą być ONLINE

• Raporty definiowane przez użytkowników

• Dowolne agregaty

• Raporty wyklikiwane – NIE SQL!!!!

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

Tłumaczenia w raportachSELECT

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

.....

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

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;

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.ndocumentidAND 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 gfanON gfan.nassignedquestionid = gfaq.nassignedquestionidAND gfan.ndocumentid = gfd.ndocumentid;

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

Kwerenda

View

Function

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ą