czemu zapytania trzymane po stronie bazy są wydajniejsze

czemu zapytania trzymane po stronie bazy są wydajniejsze
BA
  • Rejestracja:około 9 lat
  • Ostatnio:około 5 lat
  • Postów:47
0

Cześć,
Chciałbym was zapytać czemu zapytania składowane w systemie zarządzania bazą danych są wydajniejsze od zapytań zagnieżdżonych w kodzie aplikacji?
Bardzo mnie interesuje ta kwestia.
Z góry dzięki

Marcin.Miga
  • Rejestracja:prawie 17 lat
  • Ostatnio:4 dni
  • Postów:2792
1

Bo w wielu systemach ich wyniki są keszowane.

WL
  • Rejestracja:około 21 lat
  • Ostatnio:około 2 miesiące
  • Postów:1082
0

A poza tym, to nie zawsze prawda... A raczej - nie ma na tak postawione pytanie odpowiedzi zero-jedynkowej.
@bananananafu Skąd to twierdzenie, jakiś konkretny przykład?
Jeśli porównujesz wydajność select, to oczywiście zwróciłeś uwagę na czas wysyłki danych do klienta i czas obróbki tych danych przez klienta? Jak spartolisz coś w aplikacji, to baz danych szybciej zwróci dane, niż aplikacja jest w stanie je odebrać.

BA
  • Rejestracja:około 9 lat
  • Ostatnio:około 5 lat
  • Postów:47
0

Gdzieś tak kiedyś przeczytałem i teraz zacząłem potrzebować odpowiedzi na to pytanie ;p
Wyczytałem, że lepiej, zeby zapytania mielił silnik bazy danych, bo jest bardziej wydajny, ale to są tylko i wyłącznie rzeczy które kiedyś przeczytałem, chyba na tym forum

WL
  • Rejestracja:około 21 lat
  • Ostatnio:około 2 miesiące
  • Postów:1082
0

Zastanów się... Jeśli zapytanie wysyłasz z aplikacji do bazy danych, to baz danych go nie "mieli"?
A może chodzi Ci o operacje sortowania/filtrowania wykonywane w aplikacji vs baza danych?
Tak czy inaczej, dalej podtrzymuje to co napisałem wcześniej; to zależy...

BA
  • Rejestracja:około 9 lat
  • Ostatnio:około 5 lat
  • Postów:47
0

Gdyby mnie to nie zastanawiało, to by nie było tego pytania. Naukę o bazach danych zacząłem niedawno, dlatego wolałem zapytać o zdanie tych, którzy wiedzą ode mnie więcej. Dzięki za wszystkie odpowiedzi:)

FI
  • Rejestracja:około 10 lat
  • Ostatnio:ponad 6 lat
  • Postów:88
1

Padła już tu częściowo odpowiedź na to pytanie:

Marcin.Miga napisał(a):

Bo w wielu systemach ich wyniki są keszowane.

Ale nie tyle są keszowane wyniki co plany zapytań w wydajniejszy sposób niż zapytania Ad Hoc (procedury są kompilowane). Dane keszowane są i dla Ad Hoc i dla procedur w tzw buffer cachu jeśli mówimy o SQL Server.
Po drugie kwestia możliwości optymalizacji zapytań z aplikacji. Tu też często są ograniczone możliwości optymalizacji jakiś frameworków.
Być może utrzymanie, łatwiej jest poprawić procedurę w SQL niż wydawać nową wersję aplikacji, ale to już są zalety w kwestii organizacji pracy. Tak samo dla administratora SQL łatwiej analizować problemy wydajnościowe.
No to powiedzmy takie podstawowe zalety.


Szkolenia, audyty, konsultacje SQL Server
Radkomp, sqlszkolenia
MCTS, MCiTP, MCSA, MCSE, MCT
http://sqlszkolenia.pl
WL
  • Rejestracja:około 21 lat
  • Ostatnio:około 2 miesiące
  • Postów:1082
0
firefox napisał(a):

Padła już tu częściowo odpowiedź na to pytanie:

Marcin.Miga napisał(a):

Bo w wielu systemach ich wyniki są keszowane.

Ale nie tyle są keszowane wyniki co plany zapytań w wydajniejszy sposób niż zapytania Ad Hoc (procedury są kompilowane). Dane keszowane są i dla Ad Hoc i dla procedur w tzw buffer cachu jeśli mówimy o SQL Server.

Jeśli już mówimy o SQL Server, to dla zapytań sparametryzowanych plan zapytań jest kompilowany i keszowany w dokładnie ten sam sposób co do procedury składowanej. Rożnica jest taka, że dla procedury robi się to raz podczas "kompilacji", a dla zapytań ad-hoc podczas "preparacji".
Dopóki takie spreparowane zapytanie istnieje w danej sesji, doputy plan jest w keszu.
Szczerze? Tam gdzie nie ma absolutnej potrzeby (czyli np. skomplikowane przetwarzanie jakiś danych), nie używam procedur. Każde zapytanie z aplikacji jest parametryzowane, żadnego sklejania stringów i hardcodowania wartości parametrów. Takiego zapytania SQL Server nie jest w stanie optymalizować i trzymać dla nie planu zapytania w keszu. Podobnie jest i w innych bazach danych...

firefox napisał(a):

Po drugie kwestia możliwości optymalizacji zapytań z aplikacji. Tu też często są ograniczone możliwości optymalizacji jakiś frameworków.
Być może utrzymanie, łatwiej jest poprawić procedurę w SQL niż wydawać nową wersję aplikacji, ale to już są zalety w kwestii organizacji pracy. Tak samo dla administratora SQL łatwiej analizować problemy wydajnościowe.
No to powiedzmy takie podstawowe zalety.

To jest już ograniczenie danej technologii, a nie żadna przewaga SP.

0

Niechęć do stosowania zapytań (widoków) i procedur przechowywanych wynika pewnie z braku doświadczenia w pisaniu kodu SQL. Bez rozpisywania się już klika razy sam byłem zmuszony przenieść zapytania realizowane bezpośrednio w kodzie programu do bazy SQL właśnie ze względu na wydajność. Jedyną poważną wadą jest konieczność aktualizacji bazy (wykonywanie jakiś skryptów SQL czy ręcznie czy też automatycznie) przy okazji aktualizacji samej aplikacji.

WL
  • Rejestracja:około 21 lat
  • Ostatnio:około 2 miesiące
  • Postów:1082
5
cw1 napisał(a):

Niechęć do stosowania zapytań (widoków) i procedur przechowywanych wynika pewnie z braku doświadczenia w pisaniu kodu SQL.

Moim zdaniem jest dokładnie odwrotnie. SP (Stored Procedure - procedura składowana) zapewnia jednolity dostęp do danych niezależnie od aplikacji. I to jest zaleta, zwłaszcza dla kogoś kto tak naprawdę nie wie i nie rozumie co się dzieje w serwerze.
Miałem już do czynienia z systemem, który posiadał ponad 12 tyś procedur. Na wszystko. Utrzymanie tego czegoś to była dopiero "twórcza" praca...
Widziałem też inny, który dla zwykłej prostej operacji wyświetlenia listy dokumentów robił tak:

  1. Odpalanie jednej procedury, która zwracała ID rekordów do listy
  2. Odpalanie procedury ładowania wiersza, dla każdego wiersza z listy z pkt. 1 (sic!)
    Pewnie autor tego cuda tez przeczytał, że procedury są szybsze...
cw1 napisał(a):

Bez rozpisywania się już klika razy sam byłem zmuszony przenieść zapytania realizowane bezpośrednio w kodzie programu do bazy SQL właśnie ze względu na wydajność. Jedyną poważną wadą jest konieczność aktualizacji bazy (wykonywanie jakiś skryptów SQL czy ręcznie czy też automatycznie) przy okazji aktualizacji samej aplikacji.

Tu już nie wytrzymam... To bzdura. Nie ma prostej odpowiedzi, że to samo będzie działało szybciej tylko dlatego że jest w SP. Wiele zależy od tego, jak to było napisane.
Jeśli ktoś w aplikacji pobiera dane, a potem dla każdego wiersza wykonuje zapytanie, które coś tam dobiera z bazy, zamiast to przepisać na złączenia to sorry. Będzie to działało jak kupa. I wtedy faktycznie "przepisałem to na SP i teraz działa 100x szybciej" ma sens. Tylko, to nie do końca prawda...

Aktualizacje bazy danych to jest horror przy często zmieniającym się kodzie, gdzie tej logiki w bazie jest za dużo.
Wielokrotnie obserwuje duże systemy napisane wg "cała logika w bazie", że programiści producenta sami nie widzą co dokładnie się dzieje. Wszystko przez poplątany i zakręcony kod w serwerze, gdzie procedur jest za dużo, używane są wszędzie, zagnieżdża się wywołanie jednej SP w innej, a ta pierwsze wywołana jest przez ciąg triggerów...

I żeby była jasność. Nie jestem przeciwnikiem SP. Ale twierdzę, że trzeba podejść do tematu na zimno i pełnym zrozumieniem zasad. A tu mamy sytuację, gdzie "młody" oczekuje odpowiedzi zero-jedynkowej - co jest lepsze. Nie istnieje jednoznaczna odpowiedź na takie pytanie bez żadnego kontekstu!
A jeśli ktoś twierdzi, że SP są rozwiązaniem wszystkich (powiedzmy - większości) problemów z wydajnością itp. - to po prostu nie do końca ma pojęcie o czym mówi.

ŁF
Podpisuję się pod tym co napisałeś obiema ręcamy. Swoją drogą świetne podejście do tematu, nie kategoryczne za czy przeciw, tylko dobieranie rozwiązań do potrzeb. Tak to działa, nie każde rozwiązanie wszędzie się sprawdzi.
fasadin
  • Rejestracja:ponad 13 lat
  • Ostatnio:prawie 3 lata
  • Postów:4882
0

"byłem zmuszony przenieść zapytania realizowane bezpośrednio w kodzie programu do bazy SQL"

W wiekszosci w kodzie mozesz zrobic to samo to w bazie danych tylko trzeba znac interfejs (i zeby ten interfejs nie byl skopany). Takze bardziej obstawialbym ze Twoja znajomosc programowania i interfejsu jakiego uzywaliscie jest slaba niz to ze w bazie dziala szybciej niz z kodu

edytowany 1x, ostatnio: fasadin
ŁF
Moderator
  • Rejestracja:ponad 22 lata
  • Ostatnio:3 dni
6

Fajna dyskusja się wywiązała, więc dorzucę swoje trzy grosze w temacie.
Generalnie chcemy mieć kod tani w utrzymaniu, więc przejrzysty, przykryty testami, łatwo poddający się automatycznemu refactoringowi, SOLID, DRY, KISS i tak dalej. Dlatego moim prywatnym zdaniem chciałbym mieć ORM zapewniający automatyczne mapowanie struktury bazy danych na klasy i powiązania pomiędzy klasami. Jeśli zostanie dołożone/usunięte/wyedytowane pole tabeli, pojawi się sp albo coś zmieni się w view - automat to wszystko ogarnie i przeważnie w przypadku niekompatybilnych zmian kod wywali się już na etapie kompilacji. Jeśli nie, to z dużym prawdopodobieństwem zrobią to testy. Logika biznesowa jest w jednym miejscu, zorganizowana w klasy (oby nieduże), nie trzeba robić protez typu wysyłanie maila czy komunikacja z webserwisem z poziomu sql. Do tego miejsca wygląda to tak, jak bym chciał, żeby to było.
Czasem jednak potrzebujemy zajebistej wydajności. Mamy np. kilkaset i więcej requestów na sekundę. Gdzie się da można aplikację przykryć cachem, CDN, Redisem itp, jednak istnieją sytuacje, kiedy te kilka tysięcy zapytań na sekundę musi trafić prosto do bazy. Można iść w farmę sql, można też wyciskać z bazy wszystko co się da, czasem jedno i drugie. Skoro zachodzi taka potrzeba, to optymalizuje się bazę danych i komunikację z nią, denormalizuje dane, przenosi część logiki do procedur składowanych, godzinami ślęczy się nad planami zapytań.

I tu lekcja, którą wyniosłem z ostatniej pracy, gdzie spier**one było wszystko - od architektury systemu, przez bazę danych i kod C#, do zarządzania wytwarzaniem kodu - lekcja jak się nie robi się oprogramowania. Priorytetem powinno być łatwe utrzymanie kodu, dopiero potem wydajność. Zastałem system, który został napisany w całości z myślą o wydajności - same sp, systemy różnych firm gadały ze sobą bezpośrednio przez bazę danych, po trzy osobne bazy danych dla każdego z klientów (a miało być ich kilkuset), jednocześnie brak dokumentacji, brak specyfikacji (!), nawet brak komentarzy przy commitach. OK, można by powiedzieć, że jest słabo, ale przynajmniej mamy szybki system (i tak faktycznie było), ale... rdzeń systemu, o którym mowa, został przykryty cache'ami w zewnętrznych aplikacjach, aplikacje przykryte blobami i CDN i raptem okazało się, że do rdzenia trafia raptem kilka RPS. Zostaliśmy z nieczytelnym, nieutrzymywalnym, nierozwojowym systemem, gdzie człowiek który napisał 95% tego gówna załamał się w końcu i odszedł z firmy zabierając prawie całą wiedzę na temat core'a. Ok, wynika to w głównej mierze z braku dokumentacji, testów i bardzo słabego kodu, ale te dwie rzeczy wzięły się z braku czasu na zadbanie o te rzeczy, a to dlatego, że tzw. przedwczesna optymalizacja (premature optimization) zjadła czas na inne rzeczy. Wniosek z tego taki, że trzeba bardzo BARDZO dobrze zastanowić się nad architekturą aplikacji, dobrze przemyśleć co będzie podlegało dużym obciążeniom i nie da się zbuforować, a dopiero potem siadać do optymalizacji. Zresztą jak wiadomo optymalizuje się tylko wąskie gardła, a nie cały kod (vide _13th_Dragon wciskający wszędzie preinkrementację).

Oczywiście można pisać cały system po stronie bazy danych (Oracle), można też bazę danych dotykać tylko długim kijkiem (EF), można iść w same SP, ale najlepiej jest po prostu bardzo dobrze przemyśleć całą architekturę w gronie kumatych i technicznych ludzi.

Do autora wątku - najpierw łatwe utrzymanie kodu, dopiero potem likwidacja wąskich gardeł. Z tego powodu SP, view, triggery tylko w uzasadnionych przypadkach.


FI
  • Rejestracja:około 10 lat
  • Ostatnio:ponad 6 lat
  • Postów:88
0

Z wszystkimi opiniami nie sposób się nie zgodzić. Nigdy nie ma odpowiedzi w 100% tak lub nie szczególnie jak mówimy o technicznych tematach. Zgadzam się, że wszystko zależy od wielu czynników. Myślę, że wszyscy się zgodziliśmy, że SP są z reguły wydajniejsze. Takie zresztą było pytanie, więc chyba wszyscy zgodnie odpowiedzieli. Natomiast jasne, są sytuacje w których trzymanie kodu poza SQL będzie po prostu rozsądniejsze. Procedury można tak samo skopać i będą niewydajne tak jak i kod C#, że zamiast pobrać wszystkie dane i wrzucić do jakiegoś obiektu to pobierany jest rekord po rekordzie. Zamiast pobrać wymagany set danych to pobieramy całe tabele itp itd. Nie mówiąc o zawiłych koszmarkach generowanych przez framework.
Zrypać zawsze można czy to w SQL czy w aplikacji.
Zawsze jest potrzebny rozsądek.


Szkolenia, audyty, konsultacje SQL Server
Radkomp, sqlszkolenia
MCTS, MCiTP, MCSA, MCSE, MCT
http://sqlszkolenia.pl
edytowany 1x, ostatnio: firefox
WL
  • Rejestracja:około 21 lat
  • Ostatnio:około 2 miesiące
  • Postów:1082
1
firefox napisał(a):

Z wszystkimi opiniami nie sposób się nie zgodzić. Nigdy nie ma odpowiedzi w 100% tak lub nie szczególnie jak mówimy o technicznych tematach. Zgadzam się, że wszystko zależy od wielu czynników. Myślę, że wszyscy się zgodziliśmy, że SP są z reguły wydajniejsze.

Nie, ja się z tym nie zgadzam. W typowych zastosowaniach dla systemów OLTP, czyli implementacja CRUD przy pomocy SP, to niepotrzebny kod.
Założę się, że napiszę kod w aplikacji, który będzie zdecydowanie szybciej robił UPDATE na tabeli ze 100 polami, niż jakakolwiek procedura składowana.
Dlaczego? Ano dlatego, że:

  1. Praktycznie nigdy nie ma potrzeby aktualizować wszystkich pól, często aktualizuje się tylko kilka z nich.
  2. Do SP musisz przekazać wartości wszystkich parametrów i aktualizować jak leci. Słabo.
  3. Mój DAC potrafi aktualizować tylko te dane, które się zmieniły. Dodatkowy preparuje zapytania i może je keszować, przez co utrzymuje skompilowany plan dla takich zapytań. W efekcie działa to bardzo wydajnie a jednocześnie jest efektywniejsze od "sztywnej" SP.
  4. Przez to, że aktualizuje tylko te pole, które zostały zmienione - update potrafi być wielokrotnie szybszy. Zwłaszcza jak ktoś ma fantazję i aktualizuje dane przez widok w bazie i to najlepiej niezmaterializowany (czyli wyzwalacze aktualizujące do widoku).
firefox napisał(a):

Takie zresztą było pytanie, więc chyba wszyscy zgodnie odpowiedzieli.

Też się nie zgadzam, ponieważ pytanie był tendencyjne. OP pytał nie o to co jest szybsze, tylko dlaczego SP jest szybsza. A to drobna różnica, nieprawdaż?
A ja twierdzę, że to bez znaczenia a ewentualne różnice są pomijalne. Pod warunkiem, że zapytania ad-hoc są spreparowane.
Natomiast jestem przeciwnikiem pisania SP do wszystkiego, a zwłaszcza do realizacji operacji CRUD.
Oczywiście używam SP, ale tylko tam gdzie to ma sens - a więc tam, gdzie to jest niezbędne. I chcę ich mieć relatywnie niewiele w bazie danych.

firefox napisał(a):

Natomiast jasne, są sytuacje w których trzymanie kodu poza SQL będzie po prostu rozsądniejsze. Procedury można tak samo skopać i będą niewydajne tak jak i kod C#, że zamiast pobrać wszystkie dane i wrzucić do jakiegoś obiektu to pobierany jest rekord po rekordzie. Zamiast pobrać wymagany set danych to pobieramy całe tabele itp itd. Nie mówiąc o zawiłych koszmarkach generowanych przez framework.
Zrypać zawsze można czy to w SQL czy w aplikacji.
Zawsze jest potrzebny rozsądek.

I z tym się zgadzam :)

edytowany 1x, ostatnio: wloochacz
somekind
Moderator
  • Rejestracja:około 17 lat
  • Ostatnio:minuta
  • Lokalizacja:Wrocław
0
wloochacz napisał(a):

Praktycznie nigdy nie ma potrzeby aktualizować wszystkich pól, często aktualizuje się tylko kilka z nich.

Do SP musisz przekazać wartości wszystkich parametrów i aktualizować jak leci. Słabo.

Owszem, tylko ta różnica jest pomijalna dla pojedynczego update. To tylko wysłanie kilku(set) bajtów więcej. Niektóre ORMy tak robią, i nie ma tragedii.

Mój DAC potrafi aktualizować tylko te dane, które się zmieniły. Dodatkowy preparuje zapytania i może je keszować, przez co utrzymuje skompilowany plan dla takich zapytań. W efekcie działa to bardzo wydajnie a jednocześnie jest efektywniejsze od "sztywnej" SP.

DAC to przetwornik analogowo-cyfrowy. Zakładam, że nie o to Ci chodzi. ;)
Mógłbyś podać nazwę konkretnej technologii, która to zapewnia? Czy to Twój własny twór?

Przez to, że aktualizuje tylko te pole, które zostały zmienione - update potrafi być wielokrotnie szybszy.

Testowałeś to jakoś?

FI
  • Rejestracja:około 10 lat
  • Ostatnio:ponad 6 lat
  • Postów:88
0
wloochacz napisał(a):
  1. Praktycznie nigdy nie ma potrzeby aktualizować wszystkich pól, często aktualizuje się tylko kilka z nich.
  2. Do SP musisz przekazać wartości wszystkich parametrów i aktualizować jak leci. Słabo.
  3. Mój DAC potrafi aktualizować tylko te dane, które się zmieniły. Dodatkowy preparuje zapytania i może je keszować, przez co utrzymuje skompilowany plan dla takich zapytań. W efekcie działa to bardzo wydajnie a jednocześnie jest efektywniejsze od "sztywnej" SP.
  4. Przez to, że aktualizuje tylko te pole, które zostały zmienione - update potrafi być wielokrotnie szybszy. Zwłaszcza jak ktoś ma fantazję i aktualizuje dane przez widok w bazie i to najlepiej niezmaterializowany (czyli wyzwalacze aktualizujące do widoku).

A policzyłeś czas od spreparowania/wygenerowania do wykonania? Czy liczysz tylko czas od wysłania już wygenerowanego zapytania po stronie aplikacji do jego wykonania? Policz pełny czas od request'a w aplikacji. Po drugie właśnie te parametry są kluczem bo dla dobrej procedury są budowane plany zapytań sparametryzowane.

Dodatkowo zapominamy o kwestiach bezpieczeństwa. Tak samo zminimalizowanie obciążenia sieci bo zamiast często gęsto wysyłać kilku KB kod wysyłamy tylko exec :)
Uważam temat za zamknięty, bo możemy na ten temat rozmawiać do rana i SQL'owcy powiedzą, że najlepsze są procedury a .NET'owcy, że ich zabawki :) Najczęściej praktyka mi mówi, że .NET mają takie zdanie z braku zaawansowanej wiedzy o T-SQL a SQL'owcy braku wiedzy o .NET. A może o ich doświadczeniu z developerami co bezgranicznie ufają frameworkom i bez limitu robią to co napisałem wyżej:)
Jak dobrze poszukamy w necie to są statystyki przy jakiś założeniach. Niestety, ale najlepiej wypadają te, które wywołują procedury składowane (zapewne nie w każdym przypadku - nie jest to żelazna zasada).
Raz jeszcze na koniec powtarzam, wszędzie należy zachować umiar, rozsądek a dobra architektura/model danych sam rozwiąże w praktyce naszą rozmowę :)

PS. Tabela, która posiada 100 kolumn jest chyba potworkiem a nie tabelą. Natomiast widziałem tabele zbudowane z 365 kolumn :) Niestety nadal nie znam uzasadnienia budowy takiej tabeli :)


Szkolenia, audyty, konsultacje SQL Server
Radkomp, sqlszkolenia
MCTS, MCiTP, MCSA, MCSE, MCT
http://sqlszkolenia.pl
edytowany 2x, ostatnio: firefox
xfin
Odbijanie karty na wejściu każdego ntego dnia roku? :D
FI
Możliwe, ale tabela z tego co pamiętam była tabelą pod wynik działania jakiegoś raportu który większość kolumn miał NULL a w kilka jakieś przeliczenia :)
WL
  • Rejestracja:około 21 lat
  • Ostatnio:około 2 miesiące
  • Postów:1082
0
somekind napisał(a):
wloochacz napisał(a):

Praktycznie nigdy nie ma potrzeby aktualizować wszystkich pól, często aktualizuje się tylko kilka z nich.

Do SP musisz przekazać wartości wszystkich parametrów i aktualizować jak leci. Słabo.

Owszem, tylko ta różnica jest pomijalna dla pojedynczego update. To tylko wysłanie kilku(set) bajtów więcej. Niektóre ORMy tak robią, i nie ma tragedii.

Wiem, że tak robią i czasem jest to poważny problem. Pół biedy, jak można to optymalizować, ale nic mnie tak nie wkurza jak naginanie logiki aplikacji do ograniczeń technologii vel kaskadowa aktualizacja (a raczej jej brak w pewnych przypadkach) w MS SQL.

somekind napisał(a):

Mój DAC potrafi aktualizować tylko te dane, które się zmieniły. Dodatkowy preparuje zapytania i może je keszować, przez co utrzymuje skompilowany plan dla takich zapytań. W efekcie działa to bardzo wydajnie a jednocześnie jest efektywniejsze od "sztywnej" SP.

DAC to przetwornik analogowo-cyfrowy. Zakładam, że nie o to Ci chodzi. ;)
Mógłbyś podać nazwę konkretnej technologii, która to zapewnia? Czy to Twój własny twór?

DAC - Data Access Components. Ale racja, powinienem napisać DAL...
Głównie pisze w Delphi i przede wszystkim korzystam z FireDAC + własne rozszerzenia.

somekind napisał(a):

Przez to, że aktualizuje tylko te pole, które zostały zmienione - update potrafi być wielokrotnie szybszy.

Testowałeś to jakoś?

Nie, nie testowałem - było gorzej, albo i lepiej jak kto woli...
Uważałem podobnie jak Ty teraz, do momentu aż klienci nie zaczęli kwękać, że coś wolno działa. Po krótkiej analizie i kilku testach wyszło na to co powiedziałem. Może nie jest to typowa prosta tabelka, jest to cokolwiek bardziej skomplikowane, ale co do zasady zgadza się w 100% z tym co napisałem wcześniej.

WL
  • Rejestracja:około 21 lat
  • Ostatnio:około 2 miesiące
  • Postów:1082
1
firefox napisał(a):
wloochacz napisał(a):
  1. Praktycznie nigdy nie ma potrzeby aktualizować wszystkich pól, często aktualizuje się tylko kilka z nich.
  2. Do SP musisz przekazać wartości wszystkich parametrów i aktualizować jak leci. Słabo.
  3. Mój DAC potrafi aktualizować tylko te dane, które się zmieniły. Dodatkowy preparuje zapytania i może je keszować, przez co utrzymuje skompilowany plan dla takich zapytań. W efekcie działa to bardzo wydajnie a jednocześnie jest efektywniejsze od "sztywnej" SP.
  4. Przez to, że aktualizuje tylko te pole, które zostały zmienione - update potrafi być wielokrotnie szybszy. Zwłaszcza jak ktoś ma fantazję i aktualizuje dane przez widok w bazie i to najlepiej niezmaterializowany (czyli wyzwalacze aktualizujące do widoku).

A policzyłeś czas od spreparowania/wygenerowania do wykonania? Czy liczysz tylko czas od wysłania już wygenerowanego zapytania po stronie aplikacji do jego wykonania? Policz pełny czas od request'a w aplikacji.

Oczywiście, że sprawdziłem. Zależy od zapytania, aczkolwiek bywa to kosztowne. Dlatego robię to raz i używam spreparowanego zapytania do wysyłania konkretnych komend SQL; a więc parametry są przygotowane a plan skompilowany.
Naprawdę uważasz, że nie wiem o czym piszę, prawda? Twoje prawo. Natomiast opisuję swoje doświadczenia i nie mam ochoty nikomu niczego udowadniać. Za długo w tym siedzę, żeby bawić się w takie przepychanki...

firefox napisał(a):

Po drugie właśnie te parametry są kluczem bo dla dobrej procedury są budowane plany zapytań sparametryzowane.

A dla zapytania ad-hoc nie są?
Pisze po raz 3 w tym wątku - jeśli zapytanie jest sparametryzowane, to jest traktowane identycznie jak SP. Nie używam innych ad-hoc query. Nie sklejam zapytania ze stringów...

firefox napisał(a):

Dodatkowo zapominamy o kwestiach bezpieczeństwa. Tak samo zminimalizowanie obciążenia sieci bo zamiast często gęsto wysyłać kilku KB kod wysyłamy tylko exec :)

O czym piszesz, bo nie rozumiem?

firefox napisał(a):

Uważam temat za zamknięty, bo możemy na ten temat rozmawiać do rana i SQL'owcy powiedzą, że najlepsze są procedury a .NET'owcy, że ich zabawki :) Najczęściej praktyka mi mówi, że .NET mają takie zdanie z braku zaawansowanej wiedzy o T-SQL a SQL'owcy braku wiedzy o .NET. A może o ich doświadczeniu z developerami co bezgranicznie ufają frameworkom i bez limitu robią to co napisałem wyżej:)
Jak dobrze poszukamy w necie to są statystyki przy jakiś założeniach. Niestety, ale najlepiej wypadają te, które wywołują procedury składowane (zapewne nie w każdym przypadku - nie jest to żelazna zasada).
Raz jeszcze na koniec powtarzam, wszędzie należy zachować umiar, rozsądek a dobra architektura/model danych sam rozwiąże w praktyce naszą rozmowę :)

PS. Tabela, która posiada 100 kolumn jest chyba potworkiem a nie tabelą. Natomiast widziałem tabele zbudowane z 365 kolumn :) Niestety nadal nie znam uzasadnienia budowy takiej tabeli :)

ORLY?
No popatrz... też mi się tak wydawało. Mam nieźle znormalizowaną bazę danych, z wyczuciem i bez przesady w gonieniu jakiejś tam postaci normalnej. I gdyby to była właśnie taka tabela, a nie złączenie 9 innych, to pewnie nie byłoby problemu. A że byłem leniwy, to zrobiłem z tego widok + SP aktualizujące.
Masakra wydajnościowa... Ale ok, nieważne. Ja mam inne wymagania i oczekiwania niż standardowa aplikacja OLTP.
A teksty o potworkach możesz sobie darować - mam taki a nie inny obiekt biznesowy, który ma tyle i nie mniej atrybutów. Wszystkie są istotne. I tak jest to potworek, ale raczej z gatunku wyzwań a nie złego projektu.

FI
  • Rejestracja:około 10 lat
  • Ostatnio:ponad 6 lat
  • Postów:88
0

Kolego spokojnie, ja nie oceniam Twojej bazy i nie mówię, że Ty tworzysz potworki, ale widziałem zapytania SELECT wygenerowane przez framework, które nie raz musiałem optymalizować. 100x szybciej i prościej dało radę napisać to zapytanie w T-SQL.
Dlatego też napisałem, zawsze jest potrzebne wyczucie, to co sprawdzi się w jednym nie musi w drugim. Tak samo umiejętność jednego developera nie wskazuje umiejętności developera drugiego. Być może moje doświadczenie jest negatywne, ale to nie znaczy, że każdy developer piszę tak samo.
To samo odnosi się do procedur składowanych, widziałem takie, że miały zagnieżdżone kursory gdzie pojęcie wydajność autorowi nie była znana.

Raz jeszcze powtarzam - rozsądek.
Żeby nie było tak źle jak jest to są testy pokazujące przewagę własnego kodu .NET nad wbudowanymi funkcjami obliczeniowymi. Zatem to ponownie pokazuje, że nie ma jednego idealnego wyjścia, wszystko zależy od potrzeb i modelu danych.

PS. Co do niezrozumienia tematu bezpieczeństwa wczytaj się w treść raz jeszcze i pomyśl. Myślę, że dasz radę dojść do sensu tej wypowiedzi.


Szkolenia, audyty, konsultacje SQL Server
Radkomp, sqlszkolenia
MCTS, MCiTP, MCSA, MCSE, MCT
http://sqlszkolenia.pl
edytowany 1x, ostatnio: firefox
ŁF
Moderator
  • Rejestracja:ponad 22 lata
  • Ostatnio:3 dni
0

To, że sql wygenerowany przez ORM jest długi i w dodatku wygląda nieczytelnie nie oznacza, że będzie wykonywać się wolniej niż dopieszczony, śliczny sql napisany z palca.


FI
  • Rejestracja:około 10 lat
  • Ostatnio:ponad 6 lat
  • Postów:88
0

Panowie, nie róbcie jaj - nie o ilość linii chodzi o ilość JOIN czy ilość kolumn zwracanych i nigdy nie wykorzystywanych.


Szkolenia, audyty, konsultacje SQL Server
Radkomp, sqlszkolenia
MCTS, MCiTP, MCSA, MCSE, MCT
http://sqlszkolenia.pl
Zobacz pozostałe 3 komentarze
somekind
EF jest po prostu głupi i niekonfigurowany, więc stosuje left join tam, gdzie wystarczyłby np. inner. To nie wpływa pozytywnie na wydajność.
ŁF
Nie spotkałem się z tym, ale pewnie jest tak jak mówisz. Moim zdaniem w skład każdego zadania, w którym jest użyty EF, powinna wchodzić lektura wygenerowanego zapytania + jego plan, a żeby to wymusić to plan zapytania dołączony do zadania powinien być częścią definition of done.
somekind
Dla zapytania, które w kodzie ma 10 linijek, EF potrafi wygenerować SQL na 15 stron A4 (kiedyś wydrukowaliśmy w firmie). Kto dałby radę to przeczytać ze zrozumieniem?
ŁF
I puściliście na produkcję bez analizy zapytanie, które potencjalnie mogłoby zabić bazę? Plan zapytania nawet duży da się łatwo ogarnąć, bo zwykle wystarczy spojrzeć na łączny koszt, jeśli jest bardzo mały, a danych dla których był obliczony jest dużo, to raczej nie ma co dalej analizować, a jeśli jest duży, to trzeba znaleźć najcięższe klocki + przejrzeć strzałki, czy aby pamięci za dużo nie zżerane jest. Nic skomplikowanego. Tylko trzeba być czujnym, bo czasem sumowanie kosztów poszczególnych klocków wychodzi sql serverowi ułomnie i suma wszystkiego != 100% ;-)
somekind
Wypraszam sobie - ja nic nie puszczałem. :) W ogóle pomysł raportowania za pomocą ORMa uważam za poroniony, no ale nie będę przecież poprawiał architekta, bo i tak nie posłucha.
WL
  • Rejestracja:około 21 lat
  • Ostatnio:około 2 miesiące
  • Postów:1082
0
firefox napisał(a):

Kolego spokojnie, ja nie oceniam Twojej bazy i nie mówię, że Ty tworzysz potworki, ale widziałem zapytania SELECT wygenerowane przez framework, które nie raz musiałem optymalizować. 100x szybciej i prościej dało radę napisać to zapytanie w T-SQL.
Dlatego też napisałem, zawsze jest potrzebne wyczucie, to co sprawdzi się w jednym nie musi w drugim. Tak samo umiejętność jednego developera nie wskazuje umiejętności developera drugiego. Być może moje doświadczenie jest negatywne, ale to nie znaczy, że każdy developer piszę tak samo.
To samo odnosi się do procedur składowanych, widziałem takie, że miały zagnieżdżone kursory gdzie pojęcie wydajność autorowi nie była znana.

Oho - to kolejny mit; nie używaj kursorów bo są wolne.
Są, ale nie wszystkie; zdarza mi się użyć kursorów, ze względu na pewne fiku-miku i nie jest to problem wydajnościowy.
Natomiast jest wiele typów kursorów, trzeba wiedzieć co to znaczy. Ja np. nigdy nie użyłem innego kursora jak fast_forward.

firefox napisał(a):

Raz jeszcze powtarzam - rozsądek.
Żeby nie było tak źle jak jest to są testy pokazujące przewagę własnego kodu .NET nad wbudowanymi funkcjami obliczeniowymi. Zatem to ponownie pokazuje, że nie ma jednego idealnego wyjścia, wszystko zależy od potrzeb i modelu danych.

To prawda i też byłem zdziwiony, że działa to wydajnie. Dobrym przykładem jest np. typ HierarchyID, który jest typem CLR - nie natywnym silnika. I działa to całkiem gracko.

firefox napisał(a):

PS. Co do niezrozumienia tematu bezpieczeństwa wczytaj się w treść raz jeszcze i pomyśl. Myślę, że dasz radę dojść do sensu tej wypowiedzi.

Pod warunkiem, że ma ona sens...
Bo jak rozumiem, SP są bezpieczniejsze bo... co?
SQLInjection? Nie wchodzi w grę, ponieważ używamy sparametryzowanych zapytań. Identycznie jak w przypadku SP.
Uprawnienia w bazie danych? Nie używam ich; z baza komunikuje się aplikacja - nie użytkownik wprost. Aplikacja posiada uprawniania, nie baza danych. Aplikacja działa z baza na zasadzie Application Role.

vpiotr
  • Rejestracja:ponad 13 lat
  • Ostatnio:prawie 3 lata
0
bananananafu napisał(a):

Cześć,
Chciałbym was zapytać czemu zapytania składowane w systemie zarządzania bazą danych są wydajniejsze od zapytań zagnieżdżonych w kodzie aplikacji?
Bardzo mnie interesuje ta kwestia.
Z góry dzięki

Nie "czemu", tylko "kiedy?".
Będą wydajniejsze jeśli możesz efektywnie (najlepiej nie-kursorowo) obrobić zbiór po stronie serwera zamiast go wyciągać na klienta.

Kiedy będą wolniejsze?

  1. Np. gdy to samo zapytanie stosujesz do małego podzbioru i do całej tabeli. Wtedy SP może się zoptymalizować na jeden typ wyniku i przy drugim będzie już wolna. A dynamiczny SQL zawsze się dostosuje od nowa.
  2. Kiedy masz dużo zależności między rekordami (grafy, drzewa, ostatni aktywny rekord z grupy itp)
  3. Kiedy nie masz potrzebnej (i efektywnej) funkcji wbudowanej i musisz się posiłkować jakimiś wydumanymi obliczeniami i/lub grupowaniami
ŁF
Moderator
  • Rejestracja:ponad 22 lata
  • Ostatnio:3 dni
0
vpiotr napisał(a):

Kiedy będą wolniejsze?

  1. Np. gdy to samo zapytanie stosujesz do małego podzbioru i do całej tabeli. Wtedy SP może się zoptymalizować na jeden typ wyniku i przy drugim będzie już wolna. A dynamiczny SQL zawsze się dostosuje od nowa.
  2. Kiedy masz dużo zależności między rekordami (grafy, drzewa, ostatni aktywny rekord z grupy itp)
  3. Kiedy nie masz potrzebnej (i efektywnej) funkcji wbudowanej i musisz się posiłkować jakimiś wydumanymi obliczeniami i/lub grupowaniami

Ad 1) Co to znaczy "SP może zoptymalizować się na jeden typ wyniku"? Dane zwracane przez sp nie są buforowane, buforowany jest plan zapytania, kluczem do buforu jest literalnie sql stanowiący to zapytanie. Buforowany jest plan pierwszego wykonania zapytania - czy o to Ci chodzi? Przecież dokładnie ten sam problem będzie występować dla zwykłego zapytania (oczywiście via prepared statement).
Ad 2 i 3) To samo będzie dla zwykłego zapytania.

SP w porównaniu do zwykłego zapytania rzadko bywa wolniejsza, w sumie poza technicznymi kruczkami (np. takim jak opisano w http://stackoverflow.com/questions/440944/sql-server-query-fast-but-slow-from-procedure - BTW bardzo ciekawy wątek) to nie mogę wymyślić takiego racjonalnego przypadku.


Zobacz pozostałe 2 komentarze
vpiotr
1) Która baza danych? Załóżmy że MS SQL. Może plany zapytań buforuje tak samo - chociaż nie do końca - patrz link dalej, ale SP to nie zapytanie. Procedura składowana ma swoje reguły. SP: patrz "parameter sniffing" w https://msdn.microsoft.com/pl-pl/library/ms190439%28v=sql.110%29.aspx#Recommendations, query: patrz Execution Context w https://technet.microsoft.com/en-us/library/ms181055%28v=sql.105%29.aspx To są zupełnie inne procesy.
vpiotr
A co do 2 i 3 - wygląda jakbyś myślał że piszę o SP vs query. A chodzi o przetwarzanie "SP-only" (zapytania składowane) vs "query + C#" (zapytania zagnieżdżone).
ŁF
SP to nie zapytanie? Czym w takim razie jest, jak nie zapisanym w bazie, "reużywalnym", sformalizowanym i sparametryzowanym zapytaniem? SP nie różni się niemal niczym od sparametryzowanego zapytania. Linki które podałeś nie odkrywają nic nowego, kluczem do bufora z planami zapytania jest sql, nie jego parametry, o czym już pisałem. Dlatego i sp, i "zwykłe" zapytania są identycznie buforowane, a to że ktoś sklei zapytanie zamiast użyć parametrów będzie miało identyczny wpływ zarówno na sp, jak i zwykłe zapytanie, bo - zgadnij - działają identycznie.
Vardamir
@ŁF mylisz się, plany zapytań są zapisywane w cache MSSQL ze wskazaniem czym są. Czy jest to SP, czy dynamiczny SQL, czy też ad-hoc query - to informacja o tym jest zapisywana. Później są one inaczej traktowane, tzn. zapytanie ad-hoc ma najczęściej krótszy czas życia w cache bo początkowo jest zapisywane w cache z zerowym kosztem. Więc tu też się mylisz, nie są usuwane od najstarszych, opiera się to na koszcie planu.
ŁF
@Vardamir - ok, warto wiedzieć :-)
0

Raczej nie musi być wielkich różnic w szybkości wykonania pojedynczego select/update/insert/delete w ramach SP i z serwera aplikacyjnego, a nawet dla wielu takich samych modyfikacji w różnymi parametrami (bo np. w JDBC można zastosować "batching").
Zysk dla SP może być taki, że w SP można czasem zdecydować, czy coś zrobić na bazie i jak, bez potrzeby ruchu sieciowego tam i z powrotem między bazą a serwerem aplikacyjnym tylko w celu podjęcia tej decyzji.

A co do jakiegoś kompilowania planów wykonania w SP, to nie wiem, o jakie bazy chodzi, ale raczej o jakieś niedorobione jak na dzisiejsze rozwiązania. Przecież optymalny plan zależy od wartości parametrów zapytania (owszem bywał z tym problem w Oracle'u chyba 9, ale to przecież grube lata temu), bo mogą być różne rozkłady wartości w kolumnach z kryteriami, mogą zostać policzone nowe statystyki, ktoś może dodać indeks itd.

somekind
Moderator
  • Rejestracja:około 17 lat
  • Ostatnio:minuta
  • Lokalizacja:Wrocław
1
firefox napisał(a):

Uważam temat za zamknięty, bo możemy na ten temat rozmawiać do rana i SQL'owcy powiedzą, że najlepsze są procedury a .NET'owcy, że ich zabawki :)

Nie sądzę, aby jakikolwiek dobry programista tak powiedział.

Jak dobrze poszukamy w necie to są statystyki przy jakiś założeniach. Niestety, ale najlepiej wypadają te, które wywołują procedury składowane (zapewne nie w każdym przypadku - nie jest to żelazna zasada).

Nawet jeśli w jakichś tam sztucznych testach SP wypadają jako zawsze szybsze, to na pewno nie są szybsze w tworzeniu i utrzymywaniu w rzeczywistym świecie. SP ma sens do operacji wsadowych, raportów, tego typu hurtowego przetwarzania danych. A do CRUDa są ORMy. Milisekundy tracone na wykonaniu zapytania są równoważone przez miesiące krótszej pracy nad aplikacją.

wloochacz napisał(a):

Wiem, że tak robią i czasem jest to poważny problem.

Wierzę Ci, chociaż sam nie spotkałem się z tym, żeby update pojedynczego rekordu spowalniał aplikację, albo w ogóle powodował jakieś opóźnienie zauważalne dla użytkownika.

Pół biedy, jak można to optymalizować, ale nic mnie tak nie wkurza jak naginanie logiki aplikacji do ograniczeń technologii

Z punktu widzenia logiki aplikacji nie ma znaczenia, czy updatowane są wyłącznie zmienione pola czy wszystkie. To jedynie szczegół implementacji infrastruktury. Owszem, nie jest to optymalne działanie, może się nie podobać, ale jeśli mamy z tego jakiś zysk, to w czym to może przeszkadzać?

FI
  • Rejestracja:około 10 lat
  • Ostatnio:ponad 6 lat
  • Postów:88
0
wloochacz napisał(a):

Pod warunkiem, że ma ona sens...
Bo jak rozumiem, SP są bezpieczniejsze bo... co?
SQLInjection? Nie wchodzi w grę, ponieważ używamy sparametryzowanych zapytań. Identycznie jak w przypadku SP.
Uprawnienia w bazie danych? Nie używam ich; z baza komunikuje się aplikacja - nie użytkownik wprost. Aplikacja posiada uprawniania, nie baza danych. Aplikacja działa z baza na zasadzie Application Role.

Oczywiście, że ma :) Inaczej bym nie pisał. Tak tylko bez żadnego wysiłku intelektualnego odpisze:

  1. Mając procedurę nadajesz uprawnienia tylko do procedury i jej wykonania. Bez dostępu do widoku/tabeli. Czyli użytkownik nie dostanie się do danych tabeli, może poruszać się w zakresie możliwości procedury.

  2. Czy wysyłając z aplikacji zapytanie nie wysyłasz jawnie całego SELECT/UPDATE/INSERT/DELETE? Jak kolega zauważył kilka linijek kodu EF zamienia na kilkanaście albo kilkadziesiąt Podczas gdy procedura wywoływana jest za pomocą tylko EXECa - to też sama w sobie jest zaleta. To powoduje, że trochę jest to niebezpieczne w przypadku nasłuchiwania sieci. bo nikt nie zobaczy i nie pozna w ten sposób struktury bazy. Nie widzisz nazw tabel czy widoków, kolumn czy kalkulacji a nawet RELACJI. Widzisz tylko exec z parametrami.

  3. Po trzecie choć w dzisiejszych czasach jest to mniej bolesne bo infrastruktura z reguły jest na wysokim poziomie ale w przypadku kilku set użytkowników i ilości danych jakie wędrują po sieci w odpowiedzi na zapytanie i inne procesy około SQL dokładanie dużego kodu zapytania (który jest w postaci jawnej patrz punkt 1) po sieci jest jego dodatkowym obciążeniem zamiast wysłania tylko exec.

Tak sobie myślę, że nie rozpatrujemy innej strony medalu, użytkowej. Patrzymy przez pryzmat developera. A co z adminami SQL? Teoretycznie DEV nie powinien mieć dostępu do serwera produkcyjnego, w jaki sposób zatem administrator będzie optymalizował środowisko? Chyba zgodnie z ogólnymi zasadami zgodzicie się, że to rola administratora? - oczywiście w praktyce różnie z tym bywa i czasem DEV i ADM są współdzielone - tak, można korzystać z widoków/XE, można chodzić do DEV, ale to wydłuża proces analizy.

Mam jeszcze takie zapytanie bo nie jestem specjalistą od .NET, ale czy EF daje możliwość korzystania np z HINT'ów, robienia rekurencji (bez posiłkowania się widokami) - oczywiście bez sklejania strinq'ów?

Na koniec raz jeszcze powtarzam. Nie ma złotego i idealnego rozwiązania. Wszystko zależy od sposobu wykorzystania, jakości, modelu danych, wymagań biznesowych.
Tak jak napisałem wcześniej są sytuacje w których ORM sprawdzi się po prostu lepiej, są sytuacje, w których procedura poradzi sobie lepiej. Zatem każdy przypadek powinien być rozpatrywany indywidualnie a nie ogólnie tak jak my próbujemy to zrobić w tym miejscu.
To jak jakby dyskutować, czy wyższy człowiek ma lepiej w życiu czy niższy. Każda baza jest inna, każdy ORM i proc można spaprać tak, że wyjdzie z tego chała :)


Szkolenia, audyty, konsultacje SQL Server
Radkomp, sqlszkolenia
MCTS, MCiTP, MCSA, MCSE, MCT
http://sqlszkolenia.pl
edytowany 2x, ostatnio: firefox
somekind
Relacja i tabela to synonimy.
FI
Zgadza się, ale chyba zrozumiałeś o co chodzi :)
somekind
Moderator
  • Rejestracja:około 17 lat
  • Ostatnio:minuta
  • Lokalizacja:Wrocław
1
firefox napisał(a):
  1. Czy wysyłając z aplikacji zapytanie nie wysyłasz jawnie całego SELECT/UPDATE/INSERT/DELETE? Jak kolega zauważył kilka linijek kodu EF zamienia na kilkanaście albo kilkadziesiąt Podczas gdy procedura wywoływana jest za pomocą tylko EXECa - to też sama w sobie jest zaleta. To powoduje, że trochę jest to niebezpieczne w przypadku nasłuchiwania sieci. bo nikt nie zobaczy i nie pozna w ten sposób struktury bazy.

Z drugiej strony, kod wygenerowany przez Entity Framework jest tak zobfuscowany, że nikt nie da rady się z niego niczego o bazie dowiedzieć. Gorzej z prawdziwymi ORMami.
I kto niby miałby podsłuchiwać te zapytania? Przecież one nie idą przez internet, lecz przez jakąś wewnętrzną sieć, do której nie ma dostępu nikt poza adminami.

Mam jeszcze takie zapytanie bo nie jestem specjalistą od .NET, ale czy EF daje możliwość korzystania np z HINT'ów, robienia rekurencji (bez posiłkowania się widokami) - oczywiście bez sklejania strinq'ów?

Można manipulować treścią wygenerowanego zapytania wykorzystując interceptory i dodać hinty.

M9
  • Rejestracja:prawie 10 lat
  • Ostatnio:prawie 6 lat
1

Logikę w stored procedure trzymam rzadko i tylko wtedy, gdy pozwala to zaoszczędzić czas na przesyłaniu danych z bazy do aplikacji i z powrotem i tak często wiele razy jak czegoś nie da się zrobić jednym zapytaniem (podzapytaniem). Jak jest robionych wiele zapytań czasem po prostu się może nie dać inaczej.

Niestety, testowanie jest trudniejsze. Raczej jak chce się mieć test takiej logiki to trzeba testować integracyjnie całą procedurę, co jest drogie i mniej efektywne niż logika w aplikacji, którą banalnie prosto testuje się jednostkowo. Aplikacja staje się bardziej awaryjna i droższa w utrzymaniu. Tracą na tym testy antyregresyjne.

Czasem złożone zapytania SQL trzymam w funkcjach SQL (które woła się jak procedury). Zalety są następujące:

  • mogę wymienić kod SQL bez przebudowy / redeployu aplikacji
  • skomplikowane zapytania zapisywane jako @NamedNativeQuery wcale czytelniej nie wyglądają
edytowany 3x, ostatnio: margor90
Kliknij, aby dodać treść...

Pomoc 1.18.8

Typografia

Edytor obsługuje składnie Markdown, w której pojedynczy akcent *kursywa* oraz _kursywa_ to pochylenie. Z kolei podwójny akcent **pogrubienie** oraz __pogrubienie__ to pogrubienie. Dodanie znaczników ~~strike~~ to przekreślenie.

Możesz dodać formatowanie komendami , , oraz .

Ponieważ dekoracja podkreślenia jest przeznaczona na linki, markdown nie zawiera specjalnej składni dla podkreślenia. Dlatego by dodać podkreślenie, użyj <u>underline</u>.

Komendy formatujące reagują na skróty klawiszowe: Ctrl+B, Ctrl+I, Ctrl+U oraz Ctrl+S.

Linki

By dodać link w edytorze użyj komendy lub użyj składni [title](link). URL umieszczony w linku lub nawet URL umieszczony bezpośrednio w tekście będzie aktywny i klikalny.

Jeżeli chcesz, możesz samodzielnie dodać link: <a href="link">title</a>.

Wewnętrzne odnośniki

Możesz umieścić odnośnik do wewnętrznej podstrony, używając następującej składni: [[Delphi/Kompendium]] lub [[Delphi/Kompendium|kliknij, aby przejść do kompendium]]. Odnośniki mogą prowadzić do Forum 4programmers.net lub np. do Kompendium.

Wspomnienia użytkowników

By wspomnieć użytkownika forum, wpisz w formularzu znak @. Zobaczysz okienko samouzupełniające nazwy użytkowników. Samouzupełnienie dobierze odpowiedni format wspomnienia, zależnie od tego czy w nazwie użytkownika znajduje się spacja.

Znaczniki HTML

Dozwolone jest używanie niektórych znaczników HTML: <a>, <b>, <i>, <kbd>, <del>, <strong>, <dfn>, <pre>, <blockquote>, <hr/>, <sub>, <sup> oraz <img/>.

Skróty klawiszowe

Dodaj kombinację klawiszy komendą notacji klawiszy lub skrótem klawiszowym Alt+K.

Reprezentuj kombinacje klawiszowe używając taga <kbd>. Oddziel od siebie klawisze znakiem plus, np <kbd>Alt+Tab</kbd>.

Indeks górny oraz dolny

Przykład: wpisując H<sub>2</sub>O i m<sup>2</sup> otrzymasz: H2O i m2.

Składnia Tex

By precyzyjnie wyrazić działanie matematyczne, użyj składni Tex.

<tex>arcctg(x) = argtan(\frac{1}{x}) = arcsin(\frac{1}{\sqrt{1+x^2}})</tex>

Kod źródłowy

Krótkie fragmenty kodu

Wszelkie jednolinijkowe instrukcje języka programowania powinny być zawarte pomiędzy obróconymi apostrofami: `kod instrukcji` lub ``console.log(`string`);``.

Kod wielolinijkowy

Dodaj fragment kodu komendą . Fragmenty kodu zajmujące całą lub więcej linijek powinny być umieszczone w wielolinijkowym fragmencie kodu. Znaczniki ``` lub ~~~ umożliwiają kolorowanie różnych języków programowania. Możemy nadać nazwę języka programowania używając auto-uzupełnienia, kod został pokolorowany używając konkretnych ustawień kolorowania składni:

```javascript
document.write('Hello World');
```

Możesz zaznaczyć również już wklejony kod w edytorze, i użyć komendy  by zamienić go w kod. Użyj kombinacji Ctrl+`, by dodać fragment kodu bez oznaczników języka.

Tabelki

Dodaj przykładową tabelkę używając komendy . Przykładowa tabelka składa się z dwóch kolumn, nagłówka i jednego wiersza.

Wygeneruj tabelkę na podstawie szablonu. Oddziel komórki separatorem ; lub |, a następnie zaznacz szablonu.

nazwisko;dziedzina;odkrycie
Pitagoras;mathematics;Pythagorean Theorem
Albert Einstein;physics;General Relativity
Marie Curie, Pierre Curie;chemistry;Radium, Polonium

Użyj komendy by zamienić zaznaczony szablon na tabelkę Markdown.

Lista uporządkowana i nieuporządkowana

Możliwe jest tworzenie listy numerowanych oraz wypunktowanych. Wystarczy, że pierwszym znakiem linii będzie * lub - dla listy nieuporządkowanej oraz 1. dla listy uporządkowanej.

Użyj komendy by dodać listę uporządkowaną.

1. Lista numerowana
2. Lista numerowana

Użyj komendy by dodać listę nieuporządkowaną.

* Lista wypunktowana
* Lista wypunktowana
** Lista wypunktowana (drugi poziom)

Składnia Markdown

Edytor obsługuje składnię Markdown, która składa się ze znaków specjalnych. Dostępne komendy, jak formatowanie , dodanie tabelki lub fragmentu kodu są w pewnym sensie świadome otaczającej jej składni, i postarają się unikać uszkodzenia jej.

Dla przykładu, używając tylko dostępnych komend, nie możemy dodać formatowania pogrubienia do kodu wielolinijkowego, albo dodać listy do tabelki - mogłoby to doprowadzić do uszkodzenia składni.

W pewnych odosobnionych przypadkach brak nowej linii przed elementami markdown również mógłby uszkodzić składnie, dlatego edytor dodaje brakujące nowe linie. Dla przykładu, dodanie formatowania pochylenia zaraz po tabelce, mogłoby zostać błędne zinterpretowane, więc edytor doda oddzielającą nową linię pomiędzy tabelką, a pochyleniem.

Skróty klawiszowe

Skróty formatujące, kiedy w edytorze znajduje się pojedynczy kursor, wstawiają sformatowany tekst przykładowy. Jeśli w edytorze znajduje się zaznaczenie (słowo, linijka, paragraf), wtedy zaznaczenie zostaje sformatowane.

  • Ctrl+B - dodaj pogrubienie lub pogrub zaznaczenie
  • Ctrl+I - dodaj pochylenie lub pochyl zaznaczenie
  • Ctrl+U - dodaj podkreślenie lub podkreśl zaznaczenie
  • Ctrl+S - dodaj przekreślenie lub przekreśl zaznaczenie

Notacja Klawiszy

  • Alt+K - dodaj notację klawiszy

Fragment kodu bez oznacznika

  • Alt+C - dodaj pusty fragment kodu

Skróty operujące na kodzie i linijkach:

  • Alt+L - zaznaczenie całej linii
  • Alt+, Alt+ - przeniesienie linijki w której znajduje się kursor w górę/dół.
  • Tab/⌘+] - dodaj wcięcie (wcięcie w prawo)
  • Shit+Tab/⌘+[ - usunięcie wcięcia (wycięcie w lewo)

Dodawanie postów:

  • Ctrl+Enter - dodaj post
  • ⌘+Enter - dodaj post (MacOS)