Długi czas wyświetlania danych w DataGridView

0

Otrzymałem do poprawy kawałek kodu, który wyświetla dane za pomocą DataGridView. Sekwencja operacji jest mniej więcej taka:

  1. DataGridView.DataSource = null;
  2. DataGridView.DataSource = BindingSource;
  3. w zdarzeniu DataBindingComplete dla każdej kolumny tworzony jest nowy nagłówek czyli DataGridView.Columns[i].HeaderCell = new MyHeader(....)

Oczywiście w każdym kroku są wykonywane również inne operacje, wymieniłem tylko te najważniejsze.

Problem polega na tym, że pierwsze wyświetlenie danych trwa b. długo. Czasami jest potrzeba wyświetlenia jednego wiersza ale 1k kolumn i wówczas pkt. 2 zajmuje ok. 20 s a pkt. 3 ok. 3,5 min. Ponowne wykonanie operacji 1-3 zajmuje już kilkanaście sekund a 3 tylko jedną sekundę. Nie ma znaczenia czy nazwy kolumn przy odświeżeniu danych się zmieniają czy nie. Ponowne wyświetlenie danych jest zawsze znacznie szybsze niż pierwsze (po uruchomieniu programu). Przy niewielkiej liczbie kolumn problem jest niezauważalny, jeśli jest ich kilkaset, to jest to uciążliwe.

Czy obiekt DataGridView coś sobie buforuje? Macie jakieś pomysły gdzie szukać źródła problemu? Może DataGridView ma jakiś parametr odpowiedzialny za takie zachowanie a ja go nie dostrzegam.

Z góry dziękuję za wszelką pomoc
Romek

0

Nie odnoszę się do twoich szczegółów ale ogólnie.

1.Wyświetlanie przy dużej ilości wierszy i kolumn jest baaaardzo spowalniane przez właściwość kolumn autosizemode ustawioną na auto (allcells, allcels without headers...) no bo najpierw trzeba sprawdzić szerokość wszystkich wierszy, wyznaczyć max. Dla dużej ilości wierszy i kolumn to trwa.
Wpływ na wyświetlanie ma też właściwość doublebuffered. Ustawiona na true zmniejsza migotanie ale spowalnia wyświetlanie, ale nie tak znacznie jak to pierwsze.

2.Wg MS przy dużej ilości danych w celu przyspieszenia ich wyświetlania można włączyć VirtualMode. Wtedy sam obsługujesz databinding.

3.Jeszcze pytanie, czy problem nie leży zupełnie gdzie indziej, np. w szybkości odczytu danych, jeśli kod wygląda np. tak:

  • jeśli nie ma danych to je odczytaj z bazy
  • wyświetl dane
    Oczywiście pierwsze podejście będzie trwało dłużej.
0
niemand napisał(a):

Nie odnoszę się do twoich szczegółów ale ogólnie.

1.Wyświetlanie przy dużej ilości wierszy i kolumn jest baaaardzo spowalniane przez właściwość kolumn autosizemode ustawioną na auto (allcells, allcels without headers...) no bo najpierw trzeba sprawdzić szerokość wszystkich wierszy, wyznaczyć max. Dla dużej ilości wierszy i kolumn to trwa.
Wpływ na wyświetlanie ma też właściwość doublebuffered. Ustawiona na true zmniejsza migotanie ale spowalnia wyświetlanie, ale nie tak znacznie jak to pierwsze.

2.Wg MS przy dużej ilości danych w celu przyspieszenia ich wyświetlania można włączyć VirtualMode. Wtedy sam obsługujesz databinding.

3.Jeszcze pytanie, czy problem nie leży zupełnie gdzie indziej, np. w szybkości odczytu danych, jeśli kod wygląda np. tak:

  • jeśli nie ma danych to je odczytaj z bazy
  • wyświetl dane
    Oczywiście pierwsze podejście będzie trwało dłużej.

Problemy były dwa:

  1. był włączony tryb autosize - jakie są tego konsekwencje ładnie opisałeś;
  2. ktoś namieszał ze zdarzeniami podpiętymi do grida;

Po usunięciu tych mankamentów wyświetlanie jednego wiersza danych (włącznie z pobraniem z bazy) skróciło się z 4min do 2s.

Nadal jest jednak problem z pobieraniem dużej ilości danych z bazy. Pobranie 2,2 mln wierszy (klient tego oczekuje :) zajmuje ok. 9min. W pliku tekstowym dane zajmują ok 1GB. Czy są dostępne kontrolki bazodanowe o funkcjonalnościach zbliżonych do standardowych ale szybsze? Tak długi czas pobierania danych nie jest winą aplikacji, wykonanie skryptu sql w ssms'ie też tyle trwa.

Romek

1
Romek Atomek napisał(a):

Nadal jest jednak problem z pobieraniem dużej ilości danych z bazy. Pobranie 2,2 mln wierszy (klient tego oczekuje :)

  1. A nie możesz przekonać klienta, żeby zmienił oczekiwania?
    Dane są wyświetlane na gridzie po to, żeby człowiek je oglądał. Nikt nie jest w stanie ogarnąć 2 mln wierszy.
    Na pewno jest tam jakieś filtrowanie, sortowanie po stronie klienta, czyli po wczytaniu tych 2 mln. Zamień je na filtrowanie/sortowanie po stronie bazy

  2. Skoro skrypt po stronie serwera wykonuje się długo to kontrolkami po stronie klienta nic z tym nie zrobisz.
    Możesz jedynie zmierzyć czas poszczególnych etapów:

  • wczytuję dane do pustej datatable nie podpiętej do bindingsource'a, źródło danych w datagridview null
  • podłączam datatable do bindingsource'a
  • podłaczam bingdinsource do dgv

PS. Piszesz o skrypcie sql i bindingsource, stąd zakładam, że dane są wczytywane z bazy i że operujesz na datasetach a nie np. EF.

0
niemand napisał(a):
Romek Atomek napisał(a):

Nadal jest jednak problem z pobieraniem dużej ilości danych z bazy. Pobranie 2,2 mln wierszy (klient tego oczekuje :)

  1. A nie możesz przekonać klienta, żeby zmienił oczekiwania?
    Dane są wyświetlane na gridzie po to, żeby człowiek je oglądał. Nikt nie jest w stanie ogarnąć 2 mln wierszy.
    Na pewno jest tam jakieś filtrowanie, sortowanie po stronie klienta, czyli po wczytaniu tych 2 mln. Zamień je na filtrowanie/sortowanie po stronie bazy

  2. Skoro skrypt po stronie serwera wykonuje się długo to kontrolkami po stronie klienta nic z tym nie zrobisz.
    Możesz jedynie zmierzyć czas poszczególnych etapów:

  • wczytuję dane do pustej datatable nie podpiętej do bindingsource'a, źródło danych w datagridview null
  • podłączam datatable do bindingsource'a
  • podłaczam bingdinsource do dgv

PS. Piszesz o skrypcie sql i bindingsource, stąd zakładam, że dane są wczytywane z bazy i że operujesz na datasetach a nie np. EF.

Ad.1 Liczba wyświetlanych wierszy zależy od tego co się wyklika. Czasami może to być jeden wiersz a czasami kilkadziesiąt. Aby wyświetlić dużą ilość danych trzeba podjąć świadome działanie. Zwracamy na to uwagę klientowi, że jeśli będzie chciał wyświetlić dużo wierszy, to będzie musiał poczekać.

Ad.2 Zdaję sobie sprawę, że fizyki nie przeskoczymy i ogranicza nas prędkość sieci. Wydaje mi się jednak, że każdy w etapów: wczytywanie danych do datatable, podłączenie datatable do bindingsource, podłączenie bindingsource do dgv zajmuje sporo czasu. Pytając o alternatywne kontrolki chodziło mi o przyspieszenie tych etapów.

Generalnie wyświetlanie danych trwało b. długo ponieważ parametr DataGridView.ColumnHeadersHeightSizeMode był ustawiony na AutoSize. Wyłączenie tej funkcjonalności znacznie skróciło czas potrzebny na odświeżenie danych. Na razie efekt jest zadowalający.

Mam inne pytanie. W zdarzeniu DataGridView.DataBindingComplete (czyli po każdym odświeżeniu danych) wymieniane są nagłówki kolumn (DataGridView.Columns[i].HeaderCell = new NowyHeader(...)). W konstruktorze nowego nagłówka następuje podłączenie do zdarzeń grida (np DataGridView.Scroll += NowyHeader.OnScroll - zapis jest trochę uproszczony, taka jest idea). Zastanawiam się, co się dzieje ze zdarzeniami po wielokrotnym przeładowaniu DataGridView (za każdym razem są wymieniane nagłówki i podpinane nowe zdarzenia). Czy zdarzenia, z nagłówków, które zostały usunięte są w jakiś magiczny sposób usuwane z listy? Kiedy obiekt zbędnego już nagłówka zostanie zniszczony? Autor rozwiązania nie utworzył destruktora dla klasy NowyHeader, w którym jawnie można usunąć zbędne zdarzenia.

1
  1. Żaden czlowiek nie ogarnie 2 mln rekordów. Klient pieprzy głupoty.
  2. Tak. Inne kontrolki mogą radzić sobie znacznie lepiej ale to i tak głupie rozwiązanie.
    Komercyjme gridy maja np. ciagłe ladowanie. Nieskonczoma dlugosc tabeli z ladowaniem porcjami po ileśtam rekordów.

Nie wiem czy standardowy gród ma metody BeginUpdate i EndUpdate. DevExpress ma. Znacznie przyspiesza.

0
niemand napisał(a):
  1. A nie możesz przekonać klienta, żeby zmienił oczekiwania?
    Dane są wyświetlane na gridzie po to, żeby człowiek je oglądał. Nikt nie jest w stanie ogarnąć 2 mln wierszy.
    Na pewno jest tam jakieś filtrowanie, sortowanie po stronie klienta, czyli po wczytaniu tych 2 mln. Zamień je na filtrowanie/sortowanie po stronie bazy

też mi na to wygląda. jak jest zronione wybieranie tego co ma byc wyswietlone?

1 użytkowników online, w tym zalogowanych: 0, gości: 1