Wypowiedzi
-
Aby mieć możliwość przeczytania tego posta musisz być członkiem grupy PHP w praktyce...
-
OK. Sprzęty koledzy wymieniają prawidłowo... Ja się pytam po co router skoro za nim stoi komp który robi za bramkę dla reszty sieci?
Z tego co czytam to jest modem który ma być podpięty do routera a za tym stoi komp na serwer ftp'a i drugi komp który robi udostępnianie dla reszty sieci w firmie.
Ja bym wziął te bramkę na sieć wewnętrzną i do niej podpiął modem. Potem zrobiłbym tam blokadę na połączenia z zewnątrz z wyjątkiem na port ftp'a a następnie udostępnianie na sieć.
Dodatkowo postawiłbym tam dhcp'a.
Serwer ftp jako, że inny komp to przekierowanie portu.
Po kłopocie. Nie trzeba niczego kupować... kwestia linux'a i odpowiedniej konfiguracji tego co jest... -
Daniel Wloochacz Grabowski:
Marcin Mackiewicz:
Administrator baz danych nie znający podstawowej sztuczki jak zrobić PIVOT'a za pomocą CASE?
Normalne polecił bym Ci crosstabselect * from crosstab('select "data", id_serii, wartosc from pomiary') as ct( dt date, wartosc_p text, wartosc_q text);
ale z tego co wiem to w SQLite nie ma takich funkcji....
Normalnie nienormalne ;-)
Kolego zajmuje się PostgreSQL a tam PIVOTE robi się właśnie tak... a z SQLite nie miałem do czynienia...
http://www.postgresql.org/docs/9.1/static/tablefunc.html
Mogłem przeczytać manual i podpowiedzieć ale pytający mógł zrobić to samo... Podrzuciłem tylko pomysł... -
Normalne polecił bym Ci crosstab
select * from crosstab('select "data", id_serii, wartosc from pomiary') as ct( dt date, wartosc_p text, wartosc_q text);
ale z tego co wiem to w SQLite nie ma takich funkcji.... -
Ze sprzętem super dużo nie pomogę bo mistrzem świata nie jestem. Na moje oko to dużo więcej z tego sprzętu już nie wyciśniesz.
Jeszcze tylko mam pytanie. Po co tak uparcie pozostajesz przy Windowsie na tym serwerze? Aplikacja gry tego wymaga czy jak?
Pytam bo bazy przywykłem stawiać na systemach unixowych...
Tak samo za journaling z tego co wiem odpowiada system plików partycji a przy NTFS'ach czy innych pokrewnych z rodziny Windowsa nie pomoge bo ich nie znam za dobrze i szczerze mówiąc nawet nie wiem czy tam można wyłączyć księgowanie.
Kilkadziesiąt tysięcy rekordów w tabelach w bazie to nie jest problem bo to tyle co nic. A jak sporządzane są same statystyki? Robi to aplikacja czy engine bazy w postaci zapytania SQL?
Statsy wyliczane są on-line dla gracza czy to tylko do raportowania wyników gry?
A o jakich czasach wykonywania przykładowej statystyki rozmawiamy? -
Czytałem tek tekst... tak cały...
Kolega tu dużo czytał na temat PostgreSQL i jego optymalizacji. Chciał także zastosować podstawkę sprzętową pod bazę w taki sposób jak jest napisane w manual'u dla tej bazy.
Zastanawia mnie jak wygląda struktura tej bazy i jak są tworzone zapytania sql skoro posuwasz się do dzielenia plików bazy na różne dyski dla bazy mającej kilka GB. To bardzo mała baza.
Czy na pewno wszystkie zapytania oraz struktura jest tak zoptymalizowana, że więcej wycisnąć się nie da? Czy bawiłeś się konfiguracją samej bazy?
Swego czasu tej wielkości bazy miałem postawione na 2x550Mhz i 2GB ramu DDR 300 i dostęp do danych mozolny nie był.
Co do tekstu to poruszasz w nim wiele aspektów dlatego bardzo trudno się do niego odnieść...
Na twoim miejscu bał bym się przyśpieszać wydajność przez stworzenie systemu pliku bez journaling'u i wyłączenie fsync. Jak serwer padnie i nie odtworzysz wszystkiego.
Tak samo jeżeli masz dyski SCSI albo SAS (nie pamiętam co tam pisałeś) to nie kombinuj z wrzucaniem WAL'a na jakiś dysk na USB czy jakieś SATA. Strony plików super duże nie są i mogą być obsługiwane przez szybsze dyski.
Nie powiem nic na pytanie dotyczące podziału na partycje i zachowanie się kontrolera którego używasz. W moim przypadku nie widziałem zasadniczej różnicy przy podziale dysku na partycje i bez podziału.
Jak dla mnie konfiguracja jest ok i na pewno wiesz co zrobić aby sprzętowo przyśpieszyć wydajność bazy ale czy to na pewno dobra droga?
Nie pamiętam czy pisałeś jakie planujesz obciążenie tego serwera, ilość użytkowników, ilość żądań do bazy, itp...
Do użytkowników wypowiadających się:
Nie macie wrażenia po tym tekście, że Adam orientuje się w temacie i pyta o szczegóły które zna baaardzo wąska grupa osób? -
Ubuntu 12.04 LTS amd_64; Kernel: 3.2.0-26-generic
Firefox 13.0.1: OK
Chromium 18.0.1025.168: OK
Epiphany Browser 3.4.1: OK -
Ogólnie to zależy od tego czy zbierasz do jednej tabeli czy do wielu.
Ja mam w PostgreSQL tak, że wszystkie dane loguje do jednej tabeli:
schemat::varchar, tabela::varchar, atrybut::varchar, zmiana::timestamp, uzytkownik::varchar, nowa_wartosc::varchar
W odpowiednich tabelach mam wyzwalacze które uzupełniają tabelę. Jeżeli zakładam wyzwalacz to zaraz po jego założeniu robie update kolumna = kolumna aby wpisać pierwszą wartość która jest w tabeli.
Akurat loguje wybrane pola a nie wszystkie i ten sposób się sprawdza bo zawsze wiem jaka była wartość w danym okresie czasu.Marcin Mackiewicz edytował(a) ten post dnia 03.07.12 o godzinie 09:29 -
Właśnie miałem ci to samo przekleić :)
-
Pisze drugi raz bo się rozmowa rozwinęła...
To jak sobie użytkownik posortuje, poprzekłada czy poklika nie powinno mieć znaczenia :)
Ważne aby konkretna wartość była przypisana konkretnemu identyfikatorowi. Mnie nie interesuje czy element 204 tabeli jest wyświetlany użytkownikowi w wierszu 5. User może sobie np wpisać coś w wierszu 5 a ja zrobię update w bazie danych w wierszu o id = 204 -
Bardzo dziwne pytanie... Element search[1] o wartości 3 zawsze będzie pod elementem search[1]. To samo dotyczy innych wartości tablicy. Nie ma różnicy jak masz ułożone elementy w strukturze. Zawsze zostaną zwrócone wartości na tych konkretnych miejscach tablicy. Jak chcesz mieć je w innej kolejności to użyj sortowania elementów. Wg tego kodu ostatni element w strukturze DOM będzie pierwszym elementem w tablicy. Piszesz, że chcesz mieć tak jak w DOM...
Pozmieniaj identyfikatory w DOM albo odwróć tablicę (sortowanie odwrotne) tak aby wartość elementu search[5] znalazła się w search[1]. -
Wiesz w sumie podstawowy błąd to zapisanie tej samej informacji na kilku atrybutach. Przecież przynależność do grupy to rodzaj informacji. Sama informacja powinna być przechowywana w krotkach (wierszach).
Pała dla osoby projektującej te bazę.
Skoro zmieniamy zależność mówiącą o przynależności użytkownika do grupy z 1:1 na 1:n to niezbędne jest dodanie tabeli przechowującej listę grup do których należy użytkownik.
Jeżeli tego nie poprawisz to z tego co kojarze z teoretyki poziom złożoności zapytań będzie mocno rósł. Nie wspomnę już o czasie ich wykonywania oraz potrzebnych do tego zasobach sprzętowych.
Najgorsze jednak jest to, że ilość grup jest ograniczona z góry do 2 i każdorazowe zwiększenie tego ograniczenia spowoduje, że będziesz musiał przepisywać wszystkie zapytania które wykorzystujesz.
Dodatkowa tabela, że nie będziesz musiał się tym zajmować w przyszłości. Nie powiem aby to posprzątać to trochę pracy jest ale po jej wykonaniu nie wrócisz do tego tematu już nigdy :)
Jeżeli jednak nie możesz zmieniać bazy to dodaj te tabele i przepisuj informacje z tych pól do tabeli (zestaw wyzwalaczy) tak abyś mógł pisać prostsze zapytania do bazy. Musisz tylko pamiętać aby a źródłowej tabeli wprowadzić ograniczenie takie, że: id_grupy1 <> id_grupy2Marcin Mackiewicz edytował(a) ten post dnia 30.06.12 o godzinie 19:10 -
Koledzy się uprali na select count(*) które nie użyje index'u jeżeli jakikolwiek atrybut nie posiada założonego index'u. A'propos ostatniego przykładu... Zliczamy ilość wierszy. Dlaczego zatem planer ma patrzeć na wszystkie atrybuty? Wystarczy że popatrzy na jeden. W tym wypadku najlepiej zrobić count z klucza głównego: select count(i)... Nie będzie sekwencyjnego skanu bo klucz główny z założenia dostaje index.
Pierwszą rzeczą jaką bym zrobił to partycjonowanie tej tabeli na mniejszych x tabel. Nie wiem jak stare tam są dane ale 1 tabela = 1 rok lub 1 tabela = 1 miesiąc spowodowało by ze zapytania wykonują się szybciej i możesz proces usuwania danych rozłożyć w czasie.
Proponuje dla tabeli:create table klienci (
id varchar(1),
dzien date,
stan int)
z wpisanymi tymi przykładowymi danymi zrobić zapytanieselect distinct on (stan) * from klienci where id = 'A';
To zapytanie zminimalizowane do jednego klienta zwraca te wartości których potrzebujesz (przynajmniej w moim PostgreSQL 9.1.2 tak jest).
Proponuje napisać funkcje z parametrem przyjmującym id klienta i zrobicselect nazwa_funkcji(id) from ( select distinct id from klienci);
w samej funkcji natomiast zrobicinsert into klienci_new select distinct on (stan) * from klienci where id = '$1';
Przepisuje potrzebne mi wiersze dla konkretnego klienta. Po zakończeniu starą tabelę można usunąć.
Pod żadnym pozorem nie korzystaj z identyfikatorów z tej tabeli jeżeli masz słownik klientów (po co skanować tak dużą tabelę nawet z wykorzystaniem index'u jeżeli masz o wiele krótszą).
Co do przenoszenia do tabeli historycznej proponuje napisać jakiś wyzwalacz który zapisze w historii daną tylko i wyłącznie jeżeli nastąpi zmiana stanu na inny. Jest to trochę śliskie ponieważ, jeżeli w obrębie jednego dnia nastąpi kilka zmian stanu i na końcu dnia stan będzie identyczny jak na początku to system tego nie zarejestruje. -
Oj tam. Płatności cząstkowe nie są wcale takie złe jak je malują.
Wszystko opiera się na odpowiednim przemyśleniu mechanizmu i zaprojektowaniu bazy.
Zauważ proszę, że każda wpłata (nawet 1 przelew = kwota 2 fv) jest przypisana do konkretnego kontrahenta. To samo dotyczy wysokości należności wynikającej z faktu wystawienia tych fv.
Zatem kwestia opracowania mechanizmu rozliczania należności względem wpłat...
Same fv posiadają swój identyfikator, datę wystawienia, termin zapłaty oraz formę płatności. Co za problem automatycznie rozliczać należności według np terminów płatności a jeżeli termin jest ten sam po identyfikatorze. Przy płatności zapisuje jaka kwota została rozliczona (wyjątkiem są wpłaty gotówkowe które powinny być rozliczone przy tej konkretnej fv) czyli przechowuję kwotę pozostałej należności. Jeżeli kwota do zapłaty jest równa 0 to oznacza że płatność została rozliczona. Jeżeli nie jest równa 0 to bardzo łatwo mogę obliczyć jaką kwotę wpłaty (lub całej fv) rozliczyłem:
KP - KDZ = KRW (kwota płatności - kwota płatności do zapłaty = kwota wpłaty rozliczona dla tej płatności)
Przy wpłacie natomiast pamiętałbym które płatności (lub całe fv) były rozliczane z danej wpłaty. Nie muszę pamiętać jaka kwota wpłat nie została rozliczona bo nie jest to potrzebne (przy płatnościach jest to wymagane - należy wiedzieć dla których płatności należność nie została uregulowana).
To czy wszystko zostało rozliczone wiem z salda:
SW - SP = S (suma wpłat - suma płatności = saldo)
Teraz jeżeli saldo jest ujemne to znaczy, że kontrahent nie uregulował należności w całości (pomijam branie pod uwagę terminu aby uprościć schemat). Wartość bezwzględna z tej wartości powinna być równa sumie pozostałych do zapłaty płatności (kolumna przechowująca wartość do zapłaty dla konkretnych płatności). Jeżeli wartość jest dodatnia to znaczy, że kontrahent ma nadpłatę a jego wszystkie płatności są uregulowane (kolumny do zapłaty wszędzie mają wartość 0)
Kwestia tylko nałożyć na to terminy zapłaty w przypadku fv lub terminy ściągnięcia części w przypadku płatności cząstkowych.
To ma w sumie związek z księgowaniem memoriałowym. Ale to nie działa dla wystawionych FV (bo z tego co wiem to dla każdej księgowej wystawiona FV zawsze wchodzi w przychody danego miesiąca). -
Oj tam czepia się kolega. Zauważmy, że wiek autora strony to 13 lat. Jak byłem w tym wieku to IE był wersji 4 a proce rzędu prosys 386, 486. Z aplikacjami (stronami) webowymi zaczynałem jak miałem 20. Aż się boje pomyśleć co kolega będzie młody wyczyniał za 7 lat :)
Jak mnie uczyli tworzenia stron www to się siedziało na notepad'dzie i klepało <html><body> ... i używało podstawowych 16 kolorów a o css nikt nie słyszał (przynajmniej w mojej dawnej szkole)
Mimo wymienionych wcześniej szczegółów (bo więcej dodać się nie da) ja koledze gratuluje zaciętości i chęci do poznawania / uczenia się. -
Nadal nie rozumiem idei cząstkowania kwoty należności. Liczy się tylko czy kwota należności jest równa sumie wpłat.
Weźmy:
faktura_v: id, kwota_fv, do_zaplaty, plat_termin, plat_forma
faktura: id, kwota, plat_termin, plat_forma
faktura_pozycje: id_faktury, lp_pozycji, vat, kwota_netto, produkt, opis, komentarz
wplaty_faktury: id, id_faktury, kwota_platy, rodzaj_dokumentu, id_wyciagu, lp_pozycji_wyciagu
wplaty_wyciagi: id, data_wyciagu, data_importu
wplaty_wyciagi_pozycje: id_wyciagu, lp_pozycji, id_faktury, kwota_pozycji
Faktura i fv pozycje opisuja fakture (z grubsza), Wplaty_faktury to lista wpłat dokonanych przez np KP lub przez ręczne księgowanie wyciągu z banku lub automatyczne księgowanie (np MT940).
Faktura_v to widok na bazie który zwraca listę faktur wraz z informacją o tym jaka kwota pozostała do zapłaty.
Cząstkowanie płatności to dla mnie zupełnie inna sprawa. Np. mój dostawca internetu wystawia mi jedną, zbiorczą fakturę za cały rok. Ja zaś płacę równą kwotę co miesiąc. Faktura jest jedna a płatności (polecenia zapłaty wystawiane przez dostawcę) dwanaście. Jest to swoiste rozłożenie kwoty należności na x części. Tylko w takim przypadku dzielenie FV ma sens; w każdym innym wierzyciel ma nadpłatę lub niedopłatę względem kwoty należności. Teraz każda płatność jest przypisana do fv a wpłata korelowana jest zarówno z FV jak i z konkretną płatnością. -
Grzegorz Wieczorkowski:
piki czcionek mam z innej wersji sklepu tj. PrestaShop.PL_1.4.4.1-stable i tam to wszystko działa. w sumie to też nie rozumiem dlaczego tam nie jest to załatwiane bezpośrednio utf-8 w zasadzie całego fpdf pliki podmieniłem z tego sklepu. Mapy czcionek próbowałem poszukać niestety nie udało się a konwertowanie programem tt... coś tam dalej wywaliłem go bo wcale nie chciał działać. ale skoro pliki ze sklepu presty tam działają, to zupełnie nie rozumiem dlaczego to ś u mnie nie chce.
Jakieś pomysły ??
Jeżeli tylko przy generowaniu pliku *.pdf nie ma polskich znaków i używasz gotowego narzędzia takiego jak 'fpdf' lub 'mpdf' to problemem są zawsze czcionki które mimo prawidłowego kodowania nie posiadają polskich znaków w swojej mapie. Nie pozostaje nic innego jak stworzenie własnych czcionek z prawidłową mapą. Z tego co kojarze to przy 'fpdf' jest dokładny opis jak to sobie zrobić ale nie ukrywam, że na pewno napotkasz problemy (dopasowanie tego dla mnie nie było takie proste). -
A dlaczego po prostu nie podać bazie w jakim kodowaniu ma zwracać? To przecież rozwiąże cały problem.
Szkoda, że nie ma informacji co to za baza danych...
Dla PostgreSQL:
set client_enciding = 'UTF-8';
Dla MySQL:
set names 'utf8';
set character set utf; -
Hmm,
Dziwne że przy relacji 1 faktura <-> n pozycji miałeś problem a przy relacji 1 kontrahent <-> n faktur takiego problemu nie miałeś :)
Fajny diagram tylko nie rozumiem dlaczego można przypisywać rodzaj płatności do konkretnej pozycji. Z tego co wiem to cała fv jest albo przelew albo gotówka. Na to tylko się narzuca wpłaty a przy fv wylicza (lub przechowuje) ile pozostało do zapłaty... -
Moim skromnym zdaniem to kwestia indeksów. Najprawdopodobniej na samym końcu planer porównuje daty w loop'ie. Mówiłeś, że tabele są spore objętościowo... Mam nadzieje, że co jakiś czas indeksy są przebudowywane oraz jest robione vacuum :)
Czy samo zapytanie źródłowe z tymi dodatkowymi parametrami w where działa taka samo czy w każdym przypadku szybko?
Może zamiast dwóch parametrów w where spróbuj użyć jedegobeetwen data_od and data_do
Rozwiązania dwa:
Dodanie indeksów lub przeniesienie danych z where do warunków w join'ie.
Prawdą jest, że przy dużym skomplikowaniu zapytania w widoku planer glupiał i zamiast korzystać z indeksów porównywał wiersze 1:1 ale tylko przy starszych bazach (Postgres < 8.3).
Kiedyś rozwiązałem takie coś wykonywaniem zapytania w funkcji gdzie odpowiednie dane wrzucałem do warunków w join'ach co pozwalało znacznie ograniczyć ilość rekordów która zwracała tabelkę o kształcie danego widoku/tabeli.
Tak jak piszą przedmówcy wszystko do odczytania z explaine z zapytania. Michał ma rację. Każdorazowe wywołanie widoku powoduje wykonanie zapytania z definicji widoku (taki skrót do często używanych złączeń tabel) i w sumie jest traktowane prawie jakselect * from ( select ... ) as widok...
Marcin Mackiewicz edytował(a) ten post dnia 13.06.12 o godzinie 23:50