Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Relacja 1:1
Forum PHP.pl > Forum > Bazy danych
symonides
Cześć,
robię stronę dla swojej szkoły i przy projektowaniu bazy danych napotkałem kilka problemów. Wszystkie wątpliwości dotyczą relacji 1:1, którą chyba nie do końca rozumiem.

Mamy przykładowo dwie tabele: classes (grupa uczniów) i class_image (przypasowująca jedno klasowe zdjęcie do jednej klasy). Czy class_id powinno być w tabeli class_image, czy image_id w tabeli classes? Patrząc z perspektywy bazy danych to opcja druga jakoś mi bardziej odpowiada, ale patrząc już z perspektywy aplikacji, a dokładniej tego co muszę zdefiniować w ORMie to opcja ierwsza wydaje się bardziej odpowiednia.

  1. <?php
  2.  
  3. // definicje dla opcji pierwszej
  4. class Model_Class extends ORM
  5. {
  6. // klasa ma jedno zdjęcie (nie klasa neleży do zdjęcia)
  7. protected $_has_one = array(
  8. 'image' => array(
  9. 'model' => 'class_image',
  10. 'foreign_key' => 'class_id',
  11. ),
  12. );
  13. }
  14.  
  15. class Model_Class_Image extends ORM
  16. {
  17. // zdjęcie nalezy do klasy (nie zdjęcie ma jedną klasę)
  18. protected $_belongs_to = array(
  19. 'class' => array(
  20. 'model'=> 'class',
  21. 'foreign_key' => 'class_id',
  22. ),
  23. );
  24. }

Zapytanie dla pierwszego przypadku
  1. SELECT `image`.`id` AS `image:id`, `image`.`class_id` AS `image:class_id`, `image`.`path` AS `image:path`, `class`.*
  2. FROM `classes` AS `class`
  3. LEFT JOIN `class_images` AS `image` ON (`class`.`id` = `image`.`class_id`) WHERE `class`.`id` = 1 LIMIT 1

Zapytanie dla drugiego przypadku:
  1. SELECT `image`.`id` AS `image:id`, `image`.`class_id` AS `image:class_id`, `image`.`path` AS `image:path`, `class`.*
  2. FROM `classes` AS `class`
  3. LEFT JOIN `class_images` AS `image` ON (`image`.`id` = `class`.`image_id`) WHERE `class`.`id` = 1 LIMIT 1

Czy jest na to jakaś konkretna reguła, bo gdyby nie ORM to pewnie bym na to uwagi nie zwrócił?
mmmmmmm
Robisz LEFT JOINa do class_images, więc zakładasz, że tam MOŻE NIE BYĆ image. Więc w tej tabeli powinien być kluc obcy do class...
A jakie pole? Ja stosuję podwójne - zarówno w class, jak i w class_image mam referencję do drugiej tabeli.
darko
Taka "referencja zwrotna" w relacjach 1-1 często przydaje się, w przypadkach kiedy rozbudowujemy aplikację i nagle okazuje się, że na etapie projektowania bazy nie uwzględniliśmy potrzeby wyciągnięcia danych - przepraszam za określenie - od d**y strony. Jeden klucz więcej w drugiej tabeli nie wpłynie znacząco na wydajność, a może uratować wspomnianą wcześniej d*pę.
symonides
Wilekie dzięki za odpowiedź smile.gif
sazian
przypomniały mi się zajęcia z SQL'a gdzie Pan profesor powiedział że on znalazł tylko jedno zastosowanie dla relacji jeden do jednego

otóż w bazie danych było ograniczenie do kilku tysięcy kolumn na tabelę i niestety okazało się to o kilka tysięcy za mało biggrin.gif
alegorn
relacja 1:1 przydaje się. ja korzystam z niej z uwagi na optymalizację systemu

swego czasu projektowałem system, który zbierał rożne informacje o firmach.

w głównej tabeli trzymałem jedynie informacje potrzebne do utworzenia klucza głównego, dla całego projektu.
w pozostałych tabelach - często w relacjach 1:1 trzymałem pozostałe informacje.(informacje które nie były kluczowe, oraz nie były zawsze potrzebne)

dlaczego?
dzięki temu cała aplikacja działa szybciej - mogłem zastosować tylko stało znakowe typy kolumn (odpowiednie klucze etc.)
okazuje się ze ma to sens, bo do zbudowania relacji, filtrowania etc. często udaje się zbudować takie zapytanie, które potrafi korzystać z kluczy - nie ma nawet potrzeby odczytu całej tabeli..

i to działa.. wink.gif

j.
xdev
Jak to robisz na ORM'ie i jeszcze w ten sposób używasz kluczy 1:1 to to nigdy nie będzie dobrze zaprojektowane. Tym bardziej coś takiego, jeśli rysunek przechowujesz jako oddzielne pole w oddzielnej tabeli (gorzej już nie można).

Od przechowywania rysunków jest system plików a nie baza w której po drodze masz wywołanie PHP i 2 konwersje danych. To jest cholernie niewydajne. I żeby ten cholernie niewydajny kod przypadkiem zbyt szybko się nie wykonał to twój ORM tworzy do tego jeszcze najbardziej niewydajne (OUTER) joiny.

Już bardziej nieoptymalnie i w sprzeczności ze wszystkimi dobrymi praktykami przy projektowaniu baz tego chyba zrobić się nie da. Najpierw wyrzuć tego ORM-a i przejdź na coś co wspomaga SQL-a i pisz SQL a nie go zastępuj koszmarnym OOP a'la PHP. Później zapisuj te rysunki w pliku "dane/pic1_{$class_id}.jpg" prawda, że prościej? I nie trzeba dublować całej implementacji HTTP żeby obrazek wyświetlić (bo jak to poślesz bez nagłówków to ci nie będzie działać ani cache ani ściągane przyrostowe).

Admini u mnie w firmie specjalnie poograniczali pakiety do 1M, bo parę obrazków to cały serwer potrafi ubić. Twierdzą, że powinno się WIESZAĆ ludzi którzy pakują pliki do bazy. Bo nie dość że pożera ogromne ilości pamięci to jeszcze wykorzystuje wątki PHP do robienia takich bzdur jak konwersja ogromnej ilości danych. Więc zamula procesor. Jakby tego było mało to jeszcze robi sieczkę w cache serwera SQL. Idealnie to pliki statyczne się trzyma na oddzielnej subdomenie żeby można było w przyszłości podpiąć pod CDN i żebyś przy wywołaniach tych plików nie przesyłał ciastek.

>alegorn:
>często udaje się zbudować takie zapytanie, które potrafi korzystać z kluczy - nie ma nawet potrzeby odczytu całej tabeli..

Musiałeś coś źle zrobić. Może tabele nie były od dawna optymalizowane i ci się wydaje, że tak działa szybciej. Albo źle zbudowałeś klucze/partycje. To, że rozbijesz dane na kilka tabel nie ułatwia w żaden sposób korzystania z kluczy.
mmmmmmm
@xdev mam zgoła odmienne zdanie. Uważam, że po to zrobiono typ BLOB, by w nim pliki zachowywać... Problemem jest to, że jeśli programista jest do dupy i nagminnie pisze SELECT * chcąc pobrać tylko ID rekordu, mając gdzieś, co tak naprawdę siedzi w danej tabeli. I nie jest to wina adminów. Dlatego też właśnie uważam, że BLOBy powinno się trzymać w osobnej tabeli w relacji 1:1. Zresztą nie wiem, czy wiesz, ale niektóre sterowniki np. dla Oracle 10g dla .NET NIE UMOŻLIWIAŁY ODCZYTU kilku pól typu BLOB z jednego rekordu - odczytywały tylko 1, dla pozostałych zawsze zwracały Nulla.
Na korzyść przechowywania plików w bazie przemawia również to, że masz dokładnie takie same zabezpieczenia dla tego "pliku", jak i dla całej bazy - ko ma prawo odczytu, ten odczyta. W systemie plików nie zawsze tak jest.
Poza tym niektóre hostingi ograniczają ilość miejsca na pliki, za to w bazach - hulaj dusza...
darko
Zaczęła się dyskusja o wyższości przechowywania plików na dysku (bezpośrednio w systemie plikowym) nad przechowywaniem ... na dysku w plikach silnika bazodanowego. Zarówno uprawnienia, jak ograniczenia dostępu oraz zapisu i odczytu można w każdej chwili nadać i zmienić każdemu plikowi. Zdania w tym temacie zawsze będą podzielone, ponieważ nie ma jednoznacznej odpowiedzi, co jest lepsze? Wszystko zależy od charakteru serwowanych treści oraz skali projektu. Jeżeli chcecie konkretnych argumentów za jednym lub drugim rozwiązaniem, to polecam pobieżne zapoznanie się poniższymi wątkami:
http://9fingers.pl/questions/1126/
http://devpytania.pl/questions/18026/przec...-w-bazie-danych
http://forum.php.pl/index.php?showtopic=90044
xdev
No spoko, możesz mieć, tylko żeby odczytać i przesłać plik:
Serwer www: określa świeżość, wysyła nagłówki, jeśli trzeba przesłać część pliku wysyła część. Co do samego przesyłu to AFAIR teraz dzieje się to praktycznie sprzętowo. Po prostu kernel z pominięciem warstwy użytkownika czyta plik i operuje bezpośrednio na buforze karty sieciowej (różnice dochodzą do 300%). Na pewno w pewnych wypadkach serwery mogą pomijać cache OS.

Cytat
sendfile() copies data between one file descriptor and another. Because this copying is done within the kernel, sendfile() is more efficient than the combination of read(2) and write(2), which would require transferring data to and from user space.


Zapraszam tutaj, różnice mogą być kolosalne:
http://www.lighttpd.net/benchmark/
http://linuxgazette.net/issue91/tranter.html
http://stackoverflow.com/questions/3251327...ce-file-serving
Cytat
On systems where it is available, sendfile enables Apache 2 to deliver static content faster and with lower CPU utilization.


Teraz zobaczmy jak ty chcesz to zrobić:
1. Najpierw przesyłasz plik z serwera bazodanowego do klienta (PHP), programowo, być może zapisujesz jeszcze to co otrzymałeś w cache bazy chociaż sam plik bazy jest już przechowywany przez cache systemu plików.
2. Trzeba jakoś te dane obrobić po stronie PHP, żeby je umieścić w zmiennej czy tablicy. Następne kopiowanie.
3. Zamiast małego (kilkadziesiąt KB) bufora potrzebujesz: rozmiar_pliku x 2-4 pamięci RAM. Bo fcgi czy apache też musi gdzieś trzymać to co wypluje PHP zanim to wyśle ... =>
4a. Teraz to musisz wysłać do przeglądarki. Jak masz jakiś szybki serwer typu lighty albo nginx działający w FCGI to jesteś totalnie w dupie bo ten 1MB danych ci się zapisze na dysku (albo co gorsza w pamięci). I będziesz miał masę wątków przepychających gigabajty tych samych danych zapisanych na dysku albo w pamięci tymczasowej.
4b. W jeszcze większej dupie jesteś jeśli używasz apache i mod_php... bo nie dość że marnujesz megabajty ramu to jeszcze każdy obrazek się wysyła jako oddzielny proces. I masz masę procesów które jedyne co robią to przepychają ogromne ilości danych (znaczy nie robią nic, kopiują dane z jednego miejsca w drugie miejsce a potem w trzecie).

Tak szczerze to nie wiem co gorsze.
5. Musisz dorobić jakieś sprawdzanie świeżości, nagłówki, etc. Przez expiry czy etag, no dobra to jedno pole w bazie, ale niepotrzebna robota. A jak ci przeglądarka będzie chciała pobrać jedynie część pliku to już nie jest tak prosto. Poza tym baza najpierw całego tego ogromnego BLOB-a będzie musiała przetworzyć*
6. W odróżnieniu od PHP które masz share-nothing kiedy czytasz bądź zapisujesz "pliki" do tej bazy będziesz zatrzymywany na globalnych MUTEX-ach. Więc wydajnie to wykorzystasz jeden, najwyżej dwa rdzenie CPU.
7. Najlepsze jest to, że masz do wyboru myisam, które się nie nadaje do zapisu czegoś takiego bo przy każdym zapisie pliku będziesz przycinał odczyty. Albo innoDB w którym bloby działają nawet do 2 razy mniej wydajnie. Do tego w obu przypadkach totalnie zaśmiecisz cache mysql-a czymś co system operacyjny i tak będzie miał w pamięci.

Cytat
* MySQL internally has no optimizations to read portions of the blob – it is either read completely or not at all
http://www.mysqlperformanceblog.com/2010/0...rage-in-innodb/


Tak można byłoby trzymać pliki, jeśli server BD działałby w trybie bezpośredniego dostępu do dysku i miał wbudowany serwer HTTP i nie zaśmiecał tym cache kwerend.

Ty chcesz w wolnym PHP robić to co w szybkim C jest 3 razy wolniejsze. I to w najgorszy możliwy sposób (bo na procesach), obojętnie czy fcgi czy mod_php. Zanim osiągniesz 20% wydajności karty sieciowej to albo cię mutex-contention w mysql-u dopadnie i ludziom przestaną się wyświetlać losowe obrazki (i losowe URL-e) albo tym serwer ubijesz.

Inna sprawa, że jeśli masz bardzo mało użytkowników, to nawet coś zaimplementowanego w tak kolosalnie nieoptymalny sposób nie stanowi problemu. A PHP też ma wbudowany webserver, tylko że jakoś nikt go do poważnych zastosowań nie planuje używać smile.gif

>Na korzyść przechowywania plików w bazie przemawia również to, że masz dokładnie takie same zabezpieczenia dla tego "pliku", jak i dla całej bazy
Tak, ale to tylko dla małych projektów ma sens (i jeszcze jeśli admin jest "lewy") smile.gif

>Poza tym niektóre hostingi ograniczają ilość miejsca na pliki, za to w bazach - hulaj dusza...
Niestety, będzie jakiś wykop-efekt, to w 5 minut wylecisz. Hosting plików w porównaniu z hostingiem baz jest cholernie tani. Żeby zahostować 2TB plików to ci wystarczy dedyk za 90 złotych miesięcznie z jakimś nginxem i prockiem 2 core, żeby zahostować 2TB baz... to nawet nie wiem co byś musiał mieć smile.gif Stawiam, że ten sposób może działać nawet 20-100 razy (!) wolniej. Z resztą to ciekawy temat jak skończysz może jakich benchmark zapuścisz?

W ogóle zastanawiałeś się jak się będą wlec backupy czegoś takiego (mysqldump zapisuje dane binarne w formie tekstowej, więc jeszcze ci urosną o 30-40%). Z tego co wiem to bodajże SQL Server ma nawet typ danych który jest przeznaczony do zapisywania plików w bazie. Znaczy po prostu zapisuje te pliki na dysku a później dołącza do odpowiedzi.
darko
Jest jeszcze alternatywa dla jednego i drugiego rozwiązania - można przechowywać pliki w indeksie wyszukiwarki, np. Solr. Jest to bardzo wygodne i wydajne rozwiązanie.
xdev
To ciekawe. Ma to wbudowany webserver? Używasz do tego celu na produkcji?
darko
Standardowo ma wbudowany servlet container Jetty, można podłączyć inny. Obecnie obsługuje to to dość dużą sieć pięciu sklepów (na Magento) w kilkunastu wersjach językowych, dodatkowe możliwości to m.in:
- wyszukiwanie rozproszone
- replikacja
- load balancer
- haproxy
- wsparcie dla indeksowania i zarządzania indeksem, panel admina
- możliwość dynamicznego zarządzania core'mi w trakcie pracy usługi bez konieczności jej zatrzymywania (core switch, merge, rename, swap etc.)
Polecam
Standardowo można ustawić w konfiguracji spellckeckera, more like this, faceting, pivot search i wiele, wiele innych funkcjonalności.
alegorn
Cytat(xdev @ 1.09.2012, 20:32:05 ) *
>alegorn:
>często udaje się zbudować takie zapytanie, które potrafi korzystać z kluczy - nie ma nawet potrzeby odczytu całej tabeli..
Musiałeś coś źle zrobić. Może tabele nie były od dawna optymalizowane i ci się wydaje, że tak działa szybciej. Albo źle zbudowałeś klucze/partycje. To, że rozbijesz dane na kilka tabel nie ułatwia w żaden sposób korzystania z kluczy.


być może nie precyzyjnie wyraziłem swoja myśl. chodzi o przypadek, gdy wszystkie informacje jakie potrzebujesz wyciągnąć z danej tabeli - są w indeksie tzw 'covering index'
to ze rozbije dane na stało znakowe i zmienno znakowe - ma znaczenie, zwłaszcza gdy z tych drugich korzystamy w znacznie mniejszym stopniu.

ma znaczenie choćby dlatego ze ma mniejsza ilość danych do odczytu (operacji dyskowych).
ma ogromne znaczenie stosowanie maksymalnie krótkich i stało znakowych kolumn! toż to bez mała aksjomat przy projektowaniu wydajnych tabel/optymalizacji...

**

co do przechowywania plików graficznych w bazie danych - faktycznie są dwie szkoły.
jednak jestem zdania ze każde rozwiązanie należy dopasowywać do konkretnego problemu.

znam kilka co najmniej przypadków gdzie będzie to korzystne dla systemu (przechowywanie w bazie danych)
jeśli tych plików nie jest dużo? to dlaczego nie?
dane przechowywane poza bazą danych - nie są przez tą bazę zarządzane. często powoduje to śmietnik na serwerze.

poza tym wiesz co się dzieje z systemem plików, jeśli 'rozgarnięty' programista wrzuca wszystkie pliki do jednego katalogu? wink.gif co się stanie po przekroczeniu krytycznej wartości? bo dzieją się bardzo ciekawe rzeczy...

j.
xdev
Covering index nie ma nic do ilości pól w bazie. Co do rozdzielania, moim zdaniem to przykład przeoptymzlizowania i jakoś mnie to nie przekonuje. I tak operacją determinującą wydajność jest SEEK a nie sam odczyt. Może w jakimś super ekstremalnym przypadku, że masz dziesiątki milionów wierszy a partycji z tego zrobić nie możesz.

>ma ogromne znaczenie stosowanie maksymalnie krótkich i stało znakowych kolumn! toż to bez mała aksjomat przy projektowaniu wydajnych tabel/optymalizacji
Tylko, że rozbijając te tabelę zwiększasz a nie zmniejszasz ilość danych w bazie. Do tego dochodzą indeksy, sprawiające duże problemy przy zapisie. Nie dość że potrzebujesz 4 bajtów na ID to jeszcze indeksu do niego.

>dane przechowywane poza bazą danych - nie są przez tą bazę zarządzane. często powoduje to śmietnik na serwerze.
Nie, jeśli to porządnie oprogramujesz. Z resztą wszystkie pliki statyczne powinny być serwowane z CDN-u (żebyś cookie nie posyłał i można było ustawić jakieś dłuższe keepalive).
alegorn
Cytat
Covering index nie ma nic do ilości pól w bazie. Co do rozdzielania, moim zdaniem to przykład przeoptymzlizowania i jakoś mnie to nie przekonuje. I tak operacją determinującą wydajność jest SEEK a nie sam odczyt. Może w jakimś super ekstremalnym przypadku, że masz dziesiątki milionów wierszy a partycji z tego zrobić nie możesz.


nie jest to przykład przeoptymalizowania. podawałem ci już sensowny powód. jeśli nie będziesz w stanie wykorzystać Covering index - będziesz musiał odczytać całą/część tabeli.
nie przekonasz mnie, że nie robi różnicy odczytanie 5 stałoznakowych pól od odczytu 50 zmienno znakowych. zwłaszcza jeśli te 45 pól jest używane od wielkiego dzwonu - a pierwsze 5 jest kluczem głównym bazy danych.

czy zwiększam rozmiar bazy? być może, ale nie koniecznie.
by skorzystać z dobrodziejstwa stało znakowych kolumn - trzeba deklarować maksymalny(właściwie minimalny dla maksymalnej wartości) rozmiaru pola. - jeśli rozbiję tabele na dwie części - stało znakowy klucz główny i zmienno znakową część pozostałą - możliwe jest że to się opłaci - choć rozmiar ma tu znikome znaczenie.

jeśli masz wątpliwości - to może odśwież sobie wiedzę o różnicach między tabelą z stało znakowymi polami - a zmienno znakowymi. lektura jest zajmująca i daje dużo do myślenia. zwłaszcza jeśli walczymy o wartości rzędu setnych sekundy.
**

Cytat
>dane przechowywane poza bazą danych - nie są przez tą bazę zarządzane. często powoduje to śmietnik na serwerze.
Nie, jeśli to porządnie oprogramujesz. Z resztą wszystkie pliki statyczne powinny być serwowane z CDN-u (żebyś cookie nie posyłał i można było ustawić jakieś dłuższe keepalive).


jasne, dla prostego, banalnego zadania, na które z wykorzystaniem bazy danych poświęcę max 5h, na porządne oprogramowanie poświecę minimum kolejnych 5 -10h. już widzę jak przekonujesz klienta by zapłacił 200% więcej za stertę nadmiarowego kodu. ciekaw jestem jak długo tak będziesz mógł prosperować. przy większych projektach? jasne! ale przy banalnych, event'owych stronach? nie ma opcji. jest termin, który jak zawalisz - to tracisz projekt i klienta.

trzeba racjonalnie podchodzić do każdego projektu - i podejmować optymalne rozwiązania.
jeśli przekreślasz pewne rozwiązania - bo takie masz nawyki - nie jesteś elastycznym programistą - jesteś bez mała koderem który potrafi wykorzystać wytarte szablony. (bez obrazy - nie znam cie, i nie oceniam - obrazuję myśl )


j.
xdev
>nie jest to przykład przeoptymalizowania.
Ale od kiedy trzeba odczytywać wszystkie kolumny z tabeli? Możesz odczytać na przykład 3 z 50 równie dobrze. Część może mieć stałe znaki, część zmienną ilość i wolniejsze to nie jest (zaryzykuję, że szybsze, bo nie ma joina)... no chyba, że przechowujesz bloby.... z tym są straszne problemy.

Poza tym dla CHAR + utf8 to katastrofa. Bo każdy rekord jest większy przynajmniej (przynajmniej!) 3 razy (najdłuższy znak w utf8 zajmuje 3 bajty). No chyba, że to jakieś iso ale chyba wszyscy w tym momencie przechodzą na utf albo już przeszli.

>czy zwiększam rozmiar bazy? być może, ale nie koniecznie.
Sam dodatkowy id+indeks to minimum 6-10 bajtów per row.

>na porządne oprogramowanie poświecę minimum kolejnych 5-10h.
Ale stracisz czas robiąc coś totalnie bez sensu czyli rozbijając jedną tabelę na 2. Jedną z dynamiczną, drugą z statyczną zawartością.

>trzeba racjonalnie podchodzić do każdego projektu - i podejmować optymalne rozwiązania.
No dobra użycie CHAR może mieć sens (pomimo masy wad) ale jaki ma sens rozbijanie jednej tabeli na 2 tabele z różnego typu polami?

>jasne, dla prostego, banalnego zadania, na które z wykorzystaniem bazy danych poświęcę max 5h
Robiłem raz testy. Serwowanie 200-300kb pliku statycznego jest ok 8-10 RAZY wolniejsze niż serwowanie tego przy użyciu normalnego serwera HTTP. Do tego wysyca CPU. Jak serwujesz przez apache czy nginx to praktycznie serwer ci nic nie robi (10-15% zużycia CPU) i możesz wysycić łącze, jak serwujesz przez mysql/php to połowę procesora ci zużywa mysql, połowę PHP i masz zużycie na poziomie 100%.

>ciekaw jestem jak długo tak będziesz mógł prosperować. przy większych projektach? jasne! ale przy banalnych, event'owych stronach?
Oczywiście, że nie przy małych projektach. Myślałem, że o takich mówimy (bo po co rozbijać tabelę na 2 jeśli masz mniej niż kilka milionów wierszy?)
alegorn
xdev:: rozdzielilem dyskusje na odnosnie rozdzielenia tabel - od przechowywania plikow w bazie - nie zauwazyles tego - i polowa twojej wypowiedzi jest bez sensu (wkladasz w moje usta twierdzenia ktorych nie wyglosilem)
odpowiem na to co ma sens.

Cytat
>nie jest to przykład przeoptymalizowania.
Ale od kiedy trzeba odczytywać wszystkie kolumny z tabeli? Możesz odczytać na przykład 3 z 50 równie dobrze. Część może mieć stałe znaki, część zmienną ilość i wolniejsze to nie jest (zaryzykuję, że szybsze, bo nie ma joina)... no chyba, że przechowujesz bloby.... z tym są straszne problemy.

Poza tym dla CHAR + utf8 to katastrofa. Bo każdy rekord jest większy przynajmniej (przynajmniej!) 3 razy (najdłuższy znak w utf8 zajmuje 3 bajty). No chyba, że to jakieś iso ale chyba wszyscy w tym momencie przechodzą na utf albo już przeszli.


zejdź poziom niżej.
to ze w zwrocie otrzymujesz wybrane kolumny - nie oznacza ze silnik nie musi odczytać całości. różnica w odczycie nie trywialnych tabel, ale rzędu kilkuset tyś, a jeszcze wyraźniej kilku milionowe tabele - jest nie do przecenienia.

w stało znakowych - silnik jest w stanie obliczyć położenie interesujących go wartości z wiersza - i odczytać tylko ta wartość. w zmienno znakowych takiej możliwości nie ma. trzeba odczytać cały wiersz. to po pierwsze. (a więc różnica jaką trzeba załadować do pamięci jest ogromna!)

zauważ że pisałem o kluczu głównym bazy danych. czyli o czymś podstawowym i kluczowym dla aplikacji. to że w jednym konkretnym przypadku (odczytu wartości z oddzielonej 1:1 tabeli) być może jest kilku procentowo wolniejsze - to pozostałe operacje -1:n i n:n operujące na kluczu głównym i innych relacyjnych tabelach - zyskują na lekkości i prędkości. zysk liczony dla całej aplikacji - jest bezsporny.

pozostałe kwestie - przemieszałeś dwie oddzielne dyskusje (rozdzielałem jedną wypowiedz od drugiej ** ) nie ma więc sensu wdawać się w dyskusję dotyczącą tego.

j
xdev
Tylko od takiego przechowywania danych się odchodzi. Bo nie liczy się to czy silnik w jednym momencie może zlokalizować klucz tylko czy dane mieszczą się w pamięci. Innodb obsługuje jedynie tryb compact... w którym nawet CHAR przechowywany jest na rekordach o zmiennej długości właśnie ze względu na ogromny narzut UTF.

A takie rozdzielanie danych to było polecane dawno temu w myISAM. I tylko ze względu na fragmentację.

W innoDB masz COMPACT gdzie pierwsze 700 bajtów jest przechowywane w B-drzewie i DYNAMIC, gdzie przechowywane są tylko wskaźniki. Dzisiaj nie potrzebujesz statycznych formatów które oszczędzają CPU tylko formatów dynamicznych, bo masz szybkie CPU a mało pamięci i wolne IO.

Jeśli nawet tak to rozdzielisz to obie tabele będą przechowywane jak VARCHAR (w innoDB).

http://webcache.googleusercontent.com/sear...vns&strip=1
alegorn
być może musiałbym przeczytać dokładniej dokumentację - jeden post to asumpt do doszukania się w źródłach.

abstrahując od tego - z moich testów - jest uzysk, nie wielki (relatywnie, procentowo robi lepsze wrażenie bo zysk był często ok 0,2 s )- ale jest, a jeśli walczysz o to by aplikacja zwracała dane w max 0.5 s - ma to już ogromne znaczenie.
de facto, bez znaczenia już jakim sposobem sięga dane, mi wychodzi że jest szybciej.

z całą pewnością - ma to też sens jeśli chodzi o lepsze wykorzystanie pamięci. argumentacją bym się powtarzał z poprzednich postów, ale najzwyczajniej w świecie - mniejsza ilość danych do odczytu i przetwarzania.

korzystałeś może z silnika memory? ja kilkukrotnie i nie wyobrażam sobie korzystania z tego silnika bez rozbicia danych...


j.
xdev
To znaczy porównywałeś na zoptymalizowanej tabeli czy po czasie? Bo to faktycznie ciekawe (tzn. w sensie, że to nie powinno tak działać).
alegorn
testy przeprowadzałem wcześniej. na etapie projektowym - testowałem danymi tak do ok 1kk rekordów.
obecnie nadal monitorujemy tą bazę, jest kluczowa dla naszego projektu. (trochę ponad 2kk rekordów w tabeli głównej)

jest to projekt unijny - w dokumentacji musiałem przedstawić konkretne testy i wnioski.

j.
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.