2012-03-15 3 views
6

Mam aplikację internetową, która używa Guids jako PK w DB dla obiektu Employee i obiektu Association.Przesyłanie wielu obiektów z identyfikatorami GU IDID do klienta

Jedna strona w mojej aplikacji zwraca dużą ilość danych pokazujących wszystkie powiązania, do których mogą należeć wszyscy pracownicy.

Więc teraz, jestem wysyłania do klienta zasadniczo kilka obiektów, które wyglądają jak:

{assocation_id: guid, employees: [guid1, guid2, ..., guidN]} 

Okazuje się, że wielu pracowników należeć do wielu stowarzyszeń, więc przesyłam w dół ten sam GUID dla tych pracowników w kółko w tych różnych obiektach. Na przykład możliwe jest, że w niektórych przypadkach wysyłam 30 000 całkowitych komunikatów do wszystkich skojarzeń, z których jest tylko 500 unikatowych pracowników.

zastanawiam się, czy warto mnie budowanie jakiegoś indeksu odnośników, że ja również wysłać do klienta jak

{ 1: Guid1, 2: Guid2 ... } 

i zastąpienie wszystkich GUID w obiektach mi zesłać z tymi wskazówki,

lub po prostu gzipping odpowiedź będzie kompresować na tyle, że ten dodatkowy wysiłek nie jest tego warta?

Uwaga: proszę, nie dajcie się złapać w szczegóły, czy powinienem wysłać 30 000 danych, czy nie - to nie jest mój wybór i nic nie mogę z tym zrobić (i ja też mogę nie zmieniają Guida na ints lub longs w DB).

+0

Dlaczego po prostu nie użyjesz metody Linq Distinct()? Lub użyj DISTINCT w zapytaniu dbase? –

+0

Dlaczego zamiast tego nie wysłać listy * stowarzyszenia * na * pracowników *? – ydroneaud

+0

Więcej powodów, dla których przepustowość odpowiedzi, chciałbym oddzielić zagnieżdżone zasoby dla tego przypadku, jak sugerujesz. Możesz użyć osobnych żądań ajax dla nich lub leniwych załadować je na żądanie. – aceofspades

Odpowiedz

0

Więc to, co próbujesz osiągnąć, to kompresja słownika, prawda? http://en.wikibooks.org/wiki/Data_Compression/Dictionary_compression Co otrzymasz zamiast Guids o długości 16 bajtów to int o długości 4 bajtów. Otrzymasz słownika pełnego par wartości klucza, które będą przyporządkowywały każdy Guid do pewnej wartości int, prawda? Spowoduje to skrócenie czasu transferu, gdy jest wiele obiektów o tym samym identyfikatorze. Ale poświęci czas procesora przed przesłaniem do kompresji i po przesłaniu do rozpakowania. Jaka jest ilość przesyłanych danych? Czy to jest mb/gb/tb? Czy istnieje jakiś dobry powód, aby skompresować go przed wysłaniem?

+0

Małe liczby całkowite ** zsekwencjonowane jako JSON ** zajmują mniej miejsca jako połowa miejsca GUID i mniej niż GUID. Porównaj '' {7EDBB957-5255-4b83-A4C4-0DF664905735} "' lub '" 7EDBB95752554b83A4C40DF664905735 "' z '499' (34 lub 3 znaki). – Oleg

6

swoimi napisał na koniec pytanie następujące

Uwaga: proszę nie dać się wciągnąć w szczegółach, jeśli mam być wysyłając w dół 30.000 sztuk danych lub nie - jest to nie mój wybór i nic nie mogę z tym zrobić (i ja też nie mogę zmienić Guida na ints lub longs w DB).

Myślę, że to twój główny problem. Jeśli nie rozwiążesz głównego problemu, na przykład 10 razy zmniejszysz rozmiar przenoszonych danych, ale nadal nie rozwiążesz głównego problemu. Zastanówmy się nad pytaniem: Dlaczego tak wiele danych należy wysłać do klienta (do przeglądarki internetowej)?

Dane po stronie klienta są potrzebne , aby wyświetlić niektóre informacje dla użytkownika. Monitor nie jest tak duży, aby pokazać całkowitą liczbę 30 000 na jednej stronie. Żaden użytkownik nie jest w stanie uchwycić tak dużej ilości informacji. Jestem więc pewien, że wyświetlasz tylko niewielką część informacji. W takim przypadku należy wysłać tylko niewielką część informacji wyświetlanych przez użytkownika:.

Nie opisano, w jaki sposób guids będą używane po stronie klienta. Jeśli potrzebujesz informacji na przykład podczas edycji wiersza. Możesz przesłać dane tylko wtedy, gdy użytkownik rozpocznie edycję. W przypadku, gdy potrzebujesz transferu danych tylko dla jedno stowarzyszenie .

Jeśli potrzebujesz bezpośrednio wyświetlić guids, nie możesz wyświetlić wszystkich informacji naraz. Możesz więc wysłać informacje tylko na jedną stronę:. Jeśli użytkownik zaczyna przewijać lub uruchamiać przycisk "następna strona", możesz wysłać następną porcję danych. W ten sposób można naprawdę znacznie zmniejszyć rozmiar przesyłanych danych.

Jeśli masz żadnej możliwości przeprojektowania część aplikacji można realizować swoją pierwotną propozycję: przez zastąpienie GUID "{7EDBB957-5255-4b83-A4C4-0DF664905735}" lub "7EDBB95752554b83A4C40DF664905735" do liczby jak 123 zmniejszyć rozmiar GUID z 34 znaków do 3. Jeśli będzie wysłać dodatkowo szereg "guid mapowania" elementów jak

123:"7EDBB95752554b83A4C40DF664905735", 

można zmniejszyć pierwotnego rozmiaru danych 30000 * 34 = 1020000 (1 MB) do 300 * 39 + 30000 * 3 = 11700 + 90000 = 101700 (100 KB). Dzięki temu możesz zmniejszyć rozmiar danych w 10 razy. Użycie kompresji danych dynamicznych na serwerze sieciowym może dodatkowo zmniejszyć rozmiar danych.

W jakikolwiek sposób powinieneś sprawdzić, dlaczego strona jest tak wolna. Jeśli program działa w sieci LAN, transfer nawet 1MB danych może być wystarczająco szybki. Prawdopodobnie strona jest wolna podczas umieszczania danych na stronie internetowej. Mam na myśli następujące. Jeśli zmodyfikujesz jakiś element na stronie, wszystkie istniejące elementymuszą zostać ponownie obliczone. Jeśli chciałbyś pracować najpierw z odłączonymi obiektami DOM, a następnie umieścić całą porcję danych na stronie, możesz znacznie poprawić wydajność. Nie publikujesz w pytaniu, jakiej technologii używasz w swojej aplikacji internetowej, więc nie zamieszczam żadnych przykładów. Jeśli użyjesz jQuery na przykład, mógłbym dać przykład, który wyjaśniałby więcej o co mi chodzi.

+0

Czasami programista otrzymuje wymagania, których nie może zmienić, pomimo logiki alternatywnego podejścia. Myślę, że Davis całkiem wyraźnie wskazuje, że jest to sytuacja tutaj. – Random

+0

@Random: Jeśli można zmienić format odpowiedzi serwera, np. Zastępując go indeksem w tablicy "[Guid1, Guid2, ...]", to jeden * do * może zmienić protokół między komunikacją między serwerem a serwerem. Klient. Znamy zbyt mało informacji na temat problemu. Chciałem wspomnieć, że przeniesienie 30 000 całkowitych komunikatów dla jednej strony jest zdecydowanie * zbyt duże, aby wyświetlać istniejące informacje na stronie *. Przypuszczam, że jeśli przeanalizować problem bardziej pod kątem tego aspektu, można wielokrotnie zmniejszyć rozmiar przesyłanych danych. – Oleg

+0

Niekoniecznie się nie zgadzam. A informacje w twojej odpowiedzi są przydatne. Stwierdzam tylko, że ponieważ Davis zdaje się to rozumieć, ogranicza możliwość zastosowania twojej odpowiedzi na jego konkretny problem. – Random

2

Indeks wyszukiwania, który proponujesz, to nic innego jak "niestandardowy" schemat kompresji. Jak podaje amdmax, zwiększy to twoją wydajność, jeśli masz wiele takich samych identyfikatorów GUID, ale , więc gzip.

IMHO, dodatkowy wysiłek napisania niestandardowego kodowania nie będzie tego wart.

Oleg poprawnie stwierdza, że ​​warto pobierać dane tylko wtedy, gdy jest to potrzebne. Ale to oczywiście zależy od konkretnych wymagań.

1

jeśli po prostu gzipping odpowiedź skompresuje go na tyle, że ten dodatkowy wysiłek nie jest tego warty?
Odpowiedź brzmi: Tak, będzie to.

Skompresowanie danych usunie zbędne części tak dobrze, jak to możliwe (w zależności od algorytmu), aż do dekompresji.

Aby się upewnić, po prostu wyślij/wygeneruj dane nieskompresowane i skompresowane i porównaj wyniki. Możesz policzyć zduplikowane identyfikatory GUID, aby obliczyć, jak duży będzie Twój blok danych przy użyciu metody kompresji słownika. Ale myślę, że gzip będzie lepszy, ponieważ może również kompresować elementy składniowe, takie jak nawiasy klamrowe, dwukropki itp. Wewnątrz obiektu danych.

+0

Po przeprowadzeniu niektórych testów okazało się, że około 50% więcej danych wymaga przesłania całego pliku gzip'd, niż kompresji słownika. Niestety dość znaczny –

0

nie wiem jak dynamiczny jest dane, ale chciałbym

  • na pierwsze wezwanie wysłać dwa katalogi/słowniki mapowania krótkie IDS do długich GUID, dla swojego stowarzyszenia oraz dla swoich pracowników, np {1: AssoGUID1, 2: AssoGUID2, ...} i {1: EmpGUID1, 2: EmpGUID2, ...}. Te katalogi mogą również zawierać dodatkowe informacje o instancjach Stowarzyszeń i Pracowników; Podejrzewam, że nie wyświetlasz po prostu GUID

  • przy kolejnych połączeniach po prostu wyślij indeks Pracowników na Stowarzyszenie {1: [2,4,5], 3: [2,4], ...}, klucz będący krótkim identyfikatorem powiązania i identyfikatorami w wartości tablicy, krótkimi identyfikatorami pracowników. Biorąc pod uwagę Twój opis budowania indeksu odwrotnego: Pracownik do stowarzyszenia mogą dać lepsze rozmiar Wynik mądry (ale wyższy przetwarzanie)

Potem jej wszystko w dół do asocjacyjnych manipulacji, która jest prosta w JS.

Ponownie, jeśli twoje dane są (bardzo) dynamiczne strony serwera, oba katalogi wkrótce będą przestarzałe, a utrzymanie synchronizacji może cię bardzo kosztować.

0

Chciałbym zacząć od odpowiedzi na następujące pytania:

Jakie są wymagania eksploatacyjne? Czy są wymagania dotyczące rozmiaru? Wymagania dotyczące prędkości? Jaka jest minimalna wydajność, która jest naprawdę potrzebna?

Jakie są aktualne dane o wydajności? Jak daleko jesteś od wymagań?

Scharakteryzowałeś dane jako prawdopodobnie w większości powtórzone. Czy to normalny przypadek? Jeśli nie, co to jest?

Dwie wymienione powyżej opcje wydają się rozsądne i banalne do wdrożenia. Spróbuj utworzyć tablicę przeglądową i sprawdź, jakie zyski osiągniesz dzięki rzeczywistym zapytaniom. Spróbuj skompresować wyniki (z wyszukiwaniem i bez) i zobaczyć, jakie zyski uzyskasz.

Z mojego doświadczenia wynika, że ​​jeśli nie jesteś zbyt daleko od celu, wymagania dotyczące wydajności są często próbne i błędne.

Jeśli te opcje nie zbliżyły Cię do wymagań, cofnęłbym się o krok i sprawdził, czy wymagania są uzasadnione w czasie, w którym musisz rozwiązać problem.

To, co zrobisz, zależy od tego, których celów wydajności brakuje. Jeśli jest to rozmiar, zaczynasz być ograniczony, jeśli musisz wysłać całą listę skojarzeń w historii. Czy to naprawdę jest wymagane? Czy możesz wysłać całą listę raz, a potem tylko aktualizacje?