🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Thread View: pl.comp.objects
8 messages
8 total messages Started by Marek Wywiał Fri, 21 Apr 2006 12:10
wydajność GenericObject
#14625
Author: Marek Wywiał
Date: Fri, 21 Apr 2006 12:10
29 lines
1990 bytes
Witam.

Jestem początkujący w obiektach ale staram się używać. Mam taki
problem.

Chce wyświetlić listę towarów (sql -> php4 -> html).

1. Do inicjalizacji towaru używam klasy Produkt dziedziczącej po
GenericObject

2. Towary ładowane są do/przez Kolekcję implementującą leniwą
konkretyzację

3. Iterując Kolekcję wyciągam z każdego Produktu potrzebne mi w tym
momencie właściwości.


Dla bazy danych wygląda to jako seria zapytań typu
SELECT * FROM towar WHERE id='<ID>';

Wolałbym aby było to jedno zapytanie:
SELECT * FROM towar WHERE id IN (<ID>, <ID>, <ID>)

I nie wiem jak to zaimplementować, aby nie zaburzyć obiektowości w
moim programie.

Proszę o wskazówki (nazwę wzorca, standardowego obiektu)
google niewiele mi pomogło (zapewne znam zbyt mało słów kluczy by
odszukać interesujące mnie informacje)
Re: wydajność GenericObject
#14626
Author: Seweryn Habdank-Wojewódzki
Date: Fri, 21 Apr 2006 12:44
15 lines
1144 bytes
Witam

Marek Wywiał wrote:

> Proszę o wskazówki (nazwę wzorca, standardowego obiektu)

A wzorzec Visitor nie będzie dobry? Wie całkiem rozumiem czy problem jest po
stronie SQL, czy w programie.

Pozdrawiam.

-- 

|\/\/|   Seweryn Habdank-Wojewódzki
`\/\/   
Re: wydajność GenericObject
#14627
Author: Marek Wywiał
Date: Fri, 21 Apr 2006 13:38
23 lines
2335 bytes
Visitor uzyskuje dostęp do danych obiektu, już po jego stworzeniu
(danego obiektu) więc w optymalizacji zapytań nie pomoże.

Chodzi mi bardziej o coś w rodzaju BulkMode(??) GenericObject
aby tworzenie grupy obiektów nie odbywało się przy pomocy osobnych
zapytań (jeden select na każdy obiekt) tylko jedno zapytanie
zwracające dane dla wielu obiektów naraz, a następnie stworzenie i
zwrócenie takiej załadowanej już kolekcji.

Mogę to napisać po swojemu, ale wolałbym nie wymyślać koła od
nowa i popełniać przy tym błędy innych :)

W praktyce wygląda to tak, że wejście w kategorię produktów na
stronie (zawiera 2-10 produktów) jest szybkie i nie obciaża serwera.

Natomiast w przypadku generowaniu spersonalizowanego cennika ( ponad
400 pozycji) trwa to długo, i obciąża maszynę na tyle mocno, że
kolejne zapytania (lub co gorsza cenniki w tym czasie) przekraczają
czas wykonania php.

Ominąłem to stosując prosty Cache na plikach (dla cenników).
Ale ciekaw jestem czy jest znane rozwiązanie programistyczne tego
problemu na poziomie tworzenia obiektów.
Re: wydajność GenericObject
#14628
Author: Seweryn Habdank-Wojewódzki
Date: Fri, 21 Apr 2006 14:39
45 lines
2859 bytes
Witam

Marek Wywiał wrote:

> Chodzi mi bardziej o coś w rodzaju BulkMode(??) GenericObject
> aby tworzenie grupy obiektów nie odbywało się przy pomocy osobnych
> zapytań (jeden select na każdy obiekt) tylko jedno zapytanie
> zwracające dane dla wielu obiektów naraz, a następnie stworzenie i
> zwrócenie takiej załadowanej już kolekcji.

To już coraz bardziej nie kapuje.

> W praktyce wygląda to tak, że wejście w kategorię produktów na
> stronie (zawiera 2-10 produktów) jest szybkie i nie obciaża serwera.
> 
> Natomiast w przypadku generowaniu spersonalizowanego cennika ( ponad
> 400 pozycji) trwa to długo, i obciąża maszynę na tyle mocno, że
> kolejne zapytania (lub co gorsza cenniki w tym czasie) przekraczają
> czas wykonania php.

A gdybyś po prostu konstruował w locie zapytanie, poprzez formowanie "stringa".
Czyli poprostu jeśli tych ID jest dużo, to grupujesz je po 10, 15 ładujesz do
konstruowanego wlocie stringa (który jest zapytaniem SQL) i to wysyłasz do
bazy danych. Ladowanie do stringa 400 numerów ID też jest chyba przyciężkawe,
więc lepiej zrobić jakieś takie rozwiązanie pośrednie. Czyli pytanie w blokach
po X numerów ID.

Coś takiego:

masz listę ID_list i w niej ID'ki. Ja tniesz na K grup po N elementów i
ostatnia może być albo trochę większa niż N albo mniejsza niż N, to zależy
jaką strategią uznajesz czy pozwalasz do ostatniej dołączyć restówkę, czy
resztówka jest osobno. Można to zrobić inteligentnie i jeśli restówka jest >
N/2 to jest osobno jeśli mniejsza to dołączasz ją do ostatnije grupy N
elementowej.

Potem tworzysz automatycznie zapytania SQL z tymi ID'kami z pociętej listy i
wio każde zapytanie jest relatywnie krótkie i jest ich relatywnie niedużo.

Pozdrawiam.

-- 

|\/\/|   Seweryn Habdank-Wojewódzki
`\/\/   
Re: wydajnosc GenericObject
#14629
Author: Marek Wywial
Date: Fri, 21 Apr 2006 16:06
59 lines
2800 bytes
Chyba popelnilem skrót myslowy i nie wytlumaczylem wszystkiego :)

teraz mam tak:
// lista ID produktów, które maja zostac stworzone i wyswietlone
$arProdId = array( 1, 2, 3, 4, 5, 6, 7, 8) // pobrane selectem z bazy

//i aby otrzymac wszystkie te produky wykonuje:
$kolekcjaProduktow = Collection::createCollection($arProdId);


kolekcja wykonuje:
class Collection {
...
// po otrzymaniu tablicy z ID'ami
function createCollection($arProdId) {
  // iteruje ta tablice
  foreach($arProdId as $intProdId) {
    // i dla kazdego ID tworzy odpowiedni obiekt produkt
    $this->_object[$id] = new ProductObject($id);
  }
  return $this->_objects;
}
...
}

[1] Konstruktor ProductObject wykonuje:
..
__construct($id) {
  $this->_fields = $db->GetAll("SELECT * FROM products WHERE
id='$id'");
}

i wlasnie stad bierze sie seria zapytan do bazy

Pomyslem moze byc nadpisanie konstruktora w ProductObject aby jako
dane wejsciowe mógl pobrac dane pobrane selectem zbiorczym
wczesniej i zamiast selecta swojego uzyc te dane ? ale czy to jest
madre ?

czyli

$arProdukty = $db->getAll("SELECT * from produkty where id in(1,2,3,4);

foreach($arProdukty as $arProdukt) {
  $arrayProdukty[] = new ProduktObject($arProdukt);
}

a ProductObject:
__construct($data) {
   if(is_Array($data)) {
      $this->_fields = $data;
 } else {
   $this->_fields = $db->getAll("SELECT * from produkty WHERE
id='$data'");
}

a moze juz bredze po 5 dniach pracy :)

pozdrawiam,
Re: wydajnosc GenericObject
#14630
Author: Seweryn Habdank-Wojewódzki
Date: Fri, 21 Apr 2006 16:28
29 lines
1949 bytes
Witam

Marek Wywial wrote:

> [1] Konstruktor ProductObject wykonuje:
> ..
> __construct($id) {
>   $this->_fields = $db->GetAll("SELECT * FROM products WHERE
> id='$id'");
> }

Tego się spodziewałem. I dlatego napisałem o czytaniu paczek.

Podejdż paczkowo do tego zadania. Napisz sobie taki pod kontener z którego
będziesz budował elementy. Niech sam konstruktor nie robi select.

Rozbiłbym tworzenie obiektu od pociągania danych z bazy. Ciągnij dane z bazy w
postaci bloku, a potem blok zamieniaj na paczkę obiektów. Nie wiem jak w PHP
rozróżnia się rekordy, czyli jeśli wsadzisz ich kilka so selecta i potem
musisz je pociąć na kawałki nie tylko na pola, ale na recordy. Chyba żle też
będzie mieć selecta wszystkiego na raz, bo jak będzie tego 1000 (czy ileś tam
(musisz sprawdzić eksperymentalnie), to ten select też cię zawali.

Pozdrawiam.

-- 

|\/\/|   Seweryn Habdank-Wojewódzki
`\/\/   
Re: wydajnosc GenericObject
#14631
Author: Marek Wywiał
Date: Mon, 24 Apr 2006 11:20
6 lines
1561 bytes
Tak właśnie myślałem,

ale obawiałem się, że naruszę hermetyzację obiektów (Produkt)
jeżeli inny obiekt będzie pobierał dla niego dane do konstruktora.

Dziękuje serdecznie i pozdrawiam.
Re: wydajnosc GenericObject
#14632
Author: Seweryn Habdank-Wojewódzki
Date: Mon, 24 Apr 2006 11:37
44 lines
2226 bytes
Witam

Marek Wywiał wrote:

> ale obawiałem się, że naruszę hermetyzację obiektów (Produkt)
> jeżeli inny obiekt będzie pobierał dla niego dane do konstruktora.

EEE. Nie kapuje, czemu. Tak działają parsery XML. Przykładzik:

<plik>
<blok>
<dane>dane_1</dane>
<dane>dane_2</dane>
<dane>dane_3</dane>
<dane>dane_4</dane>
</blok>
<blok>
<dane>dane_1</dane>
<dane>dane_2</dane>
<dane>dane_3</dane>
<dane>dane_4</dane>
</blok>
<blok>
<dane>dane_1</dane>
<dane>dane_2</dane>
<dane>dane_3</dane>
<dane>dane_4</dane>
</blok>
</plik>

Jeżeli "blok" jest blokiem to parsowanie "blok" zawiera parsowania obiektów
"dane" i parsowanie "dane" przekazujesz parserowi "dane" a nie "blok" parsuje
"dane". U Ciebie po prostu będzie poziom pośredniości będziesz miał plik =
cała lista (nie pobierany jednym ciągiem bo będziesz miał paskudnego selecta),
tylko dzielisz na kawałki. Wydaje mi się, że to jest rozsądne. A w strukturze
klas nic nie powinno się zmiecić tylko dojdzie ci kilka klas obsługujących
bloki danych.

Pozdrawiam.

-- 

|\/\/|   Seweryn Habdank-Wojewódzki
`\/\/   
Thread Navigation

This is a paginated view of messages in the thread with full content displayed inline.

Messages are displayed in chronological order, with the original post highlighted in green.

Use pagination controls to navigate through all messages in large threads.

Back to All Threads