konto usunięte

Temat: W jaki sposób limitujecie wyniki w stronicowaniu?

Krzysztof D.:
od jakiegoś czasu stosuję nieco inną metodę.
doszedłem do wniosku że ludzie zwykle chcą wiedzieć, że jest następna strona, a nie że jest 10 kolejnych i rzadko kiedy skaczą X stron do przodu (oczywiście wszystko zależy czego strona dotyczy)
potrzebując zatem X rekordów wyciągam X+1. jak dostanę X+1 to znaczy że w bazie jest więcej niż X, ostatni rekord pomijam, wyświetlam na stronie stronicowanie w dół + przycisk "następna"
(a jak jest X lub mniej to znaczy, że nie ma następnej strony).
a tam gdzie jednak muszę znać ilość rekordów to upraszczam zapytanie by trwało szybciej.

proponuję zrobić sobie statystyki, które przyciski paginatora ludzie używają.

Tak się składa że robiłem wyszukiwarkę treści na jednej stronie swego czasu i zrobiliśmy statystyki wyszukiwania. Tzn szukaliśmy jakie są popularne kryteria, frazy i od tak zapisaliśmy sobie po ilu stronach przeskakuje użytkownik. W końcu jak zrobiliśmy moduł do statów to co to za problem żeby monitorował kolejną zmienną.

Na widokach z użytkownikami (lista była dostępna publicznie, nicki + opcje jak dodaj do znajomych, wyślij wiadomość, raportuj itp itd etc) prawie nikt nie wskakiwał na drugą stronę. Ale często były wyszukiwane konkretne osoby.
Ale o dziwo na liście z materiałami użytkowników, ludziska potrafiły ustawić kategorię i skoczyć 20-30 stron do przodu. Byli też tacy co skakali bezpośrednio o 10-20 stron i zaczynali np od 20. Obstawiliśmy że wcześniej musieli przeglądnąć pierwsze 20.

Wszystko odbija się od tego przy czym owo stronicowanie jest. Jeżeli dane są w jakiś konkretny sposób użyteczne to lepiej mieć nie tylko +/- i skoki o kilka stron ale nawet możliwość podania konkretnej strony.

konto usunięte

Temat: W jaki sposób limitujecie wyniki w stronicowaniu?

wszystko zależy od strony.
np. w liście użytkowników grupy na goldenline ludzie są wyświetlani alfabetycznie, może to powodować że ktoś chce skoczyć na sam koniec.

znowu w przypadku samej grupy PHP większość osób jest średnio zainteresowana skoczeniem na 15 stronę. Swoją drogą nie ma takiej opcji bo wyświetlane są opcje do 4szt + ostatnia.

facebook nie ma stronicowania. po prostu klikasz by dostać kolejny set danych.

zatem jak widać można takie kwestie rozwiązywać na różne sposoby.

konto usunięte

Temat: W jaki sposób limitujecie wyniki w stronicowaniu?

@Krzysztof, w pełni się zgadzam, ale np. nie zawsze jest to dobre,
jeden z portali społecznościowych ma właśnie takie doczytywanie danych,
i gdy chciałem odszukać cokolwiek sprzed kilku miesięcy, pasek przewijania przeglądarki zrobił się nieomal milimetrowy, a do zawiechy niewiele brakowało.

konto usunięte

Temat: W jaki sposób limitujecie wyniki w stronicowaniu?

Jeżeli dobrze rozumiem, próbujecie optymalizować szybkość stronnicowania poprzez cache ilości rekordów w bazie - imho jest to małe miki, bo count jest stosunkowo szybką operacja i ja bym go wykonywał raczej za każdym razem, chyba że miałbym rzadkie zapisy do listy stronnicowanej. Gdy np. projektowałem stronnicowanie galerii konkursowej i zgłoszeń przybywało kilkadziesiąt na minutę cache counta w bazie danych więcej by zwolnił, trzeba dobrać rozwiązanie do specyfiki danych.

Przy paginacji większym problemem jest pobieranie dalekich stron przy milionach rekordów wyników, zróbcie eksperyment, w jakim czasie limit pobierze pierwszą, a w jakim 3246 stronę na tym samym zbiorze. Dlatego właśnie fb mocno sugeruje, aby pobierać tylko ostatnie wpisy - zapytanie jest szybsze i bardziej powtarzalne, więc dobrze się cacheuje.
Arkadiusz Daniel

Arkadiusz Daniel Właściciel / Product
Owner / Team Leader
/ Programista

Temat: W jaki sposób limitujecie wyniki w stronicowaniu?

Krzysztof D.:
od jakiegoś czasu stosuję nieco inną metodę.
doszedłem do wniosku że ludzie zwykle chcą wiedzieć, że jest następna strona, a nie że jest 10 kolejnych i rzadko kiedy skaczą X stron do przodu (oczywiście wszystko zależy czego strona dotyczy)
potrzebując zatem X rekordów wyciągam X+1. jak dostanę X+1 to znaczy że w bazie jest więcej niż X, ostatni rekord pomijam, wyświetlam na stronie stronicowanie w dół + przycisk "następna"
(a jak jest X lub mniej to znaczy, że nie ma następnej strony).
a tam gdzie jednak muszę znać ilość rekordów to upraszczam zapytanie by trwało szybciej.

proponuję zrobić sobie statystyki, które przyciski paginatora ludzie używają.

Kolego chyba sobie żartujesz. Jest to proces mało obciążający jakąkolwiek aplikacje, i "obcinanie" w ten sposób funkcjonalności jest bez sensu. Aplikacje piszesz dla użytkownika, a nie dla siebie. Jeśli milisekundy dla Ciebie są nie do przyjęcia, a "obcinanie" funkcjonalności już tak, to zastanów się czy w ogóle takową robić. To czy będzie 10 czy 100 elementów w paginacji zależy od Ciebie, więc nie sądzę żeby przemyślanie napisana funkcjonalność "tnęła" aplikacje. Wracając do rozwiązania dobrym pomysłem (w moim odczuciu) wykazał się kolega opisujący dodatkową kolumnę w tabeli zawierającą informację o max. rekordzie np. w danej kategorii (liczbie). Obsłużyć to mogłaby procedura przy INSERT/UPDATE, aktualizująca tą kolumnę. Więc na upartego da się to zrobić w jednym zapytaniu.

konto usunięte

Temat: W jaki sposób limitujecie wyniki w stronicowaniu?

Na upartego to mozna z podzapytaniem..


SELECT pole1, pole2, pole3, poleN, (
SELECT COUNT( `pole1` )
FROM `table`
) AS counter
FROM `table`
Arkadiusz Daniel

Arkadiusz Daniel Właściciel / Product
Owner / Team Leader
/ Programista

Temat: W jaki sposób limitujecie wyniki w stronicowaniu?

Jakub Świegot:
Na upartego to mozna z podzapytaniem..


SELECT pole1, pole2, pole3, poleN, (
SELECT COUNT( `pole1` )
FROM `table`
) AS counter
FROM `table`

Właśnie na upartego można zrobić to w jednym zapytaniu, ale po co drodzy koledzy. Tak proste operacje powinniśmy w prosty sposób rozwiązywać. Rozwiązań będzie multum, nie zgrzeszę mówiąc, że będzie ich tyle ile komentujących ten temat. Jeśli rozwiązanie problemu jest przejrzyście napisane, wykonuje się szybko, i nie zaburza funkcjonalności użytkownikowi, to wydaje mi się, że bezsensowne jest wywarzanie otwartych drzwi.

konto usunięte

Temat: W jaki sposób limitujecie wyniki w stronicowaniu?

Arkadiusz Daniel:
Kolego chyba sobie żartujesz. Jest to proces mało obciążający jakąkolwiek aplikacje, i "obcinanie" w ten sposób funkcjonalności jest bez sensu. Aplikacje piszesz dla użytkownika, a nie dla siebie. Jeśli milisekundy dla Ciebie są nie do przyjęcia, a "obcinanie" funkcjonalności już tak, to zastanów się czy w ogóle takową robić. To czy będzie 10 czy 100 elementów w paginacji zależy od Ciebie, więc nie sądzę żeby przemyślanie napisana funkcjonalność "tnęła" aplikacje. Wracając do rozwiązania dobrym pomysłem (w moim odczuciu) wykazał się kolega opisujący dodatkową kolumnę w tabeli zawierającą informację o max. rekordzie np. w danej kategorii (liczbie). Obsłużyć to mogłaby procedura przy INSERT/UPDATE, aktualizująca tą kolumnę. Więc na upartego da się to zrobić w jednym zapytaniu.

dopóki mówimy o zwykłych stronach forum, pewnie.
co innego gdy mówimy o wyszukiwarce gdzie nie jesteś w stanie buforować zliczenia.

Jakub chciał usłyszeć inne metody to ma.
Nie wiem po co od razu to wnioskowanie ile u mnie milisekund to zajmuje ?

btw.
To na jaką podstronę tej grupy goldenline ci pozwala przejść od razu ?
bo z tego co widzę to jest opcja 1,2,3,4 - 46.
jak przejdziesz na czwartą to nadal masz tylko 5 i 6 do wyboru, więc wyklikanie się do 20-tej też czas zajmuje. Dobra opcja to jest w allegro gdzie możesz wpisać numer strony.

konto usunięte

Temat: W jaki sposób limitujecie wyniki w stronicowaniu?

Jakub Świegot:
Na upartego to mozna z podzapytaniem..


SELECT pole1, pole2, pole3, poleN, (
SELECT COUNT( `pole1` )
FROM `table`
) AS counter
FROM `table`

to podzapytanie jest w stylu - daliśmy małpie brzytwę, bo dla każdego wiersza robimy count-a , jakby to powiedzieć debilne

jak już musisz podzapytaniem to zrób tak

SELECT t.pole1, t.pole2, t.pole3, y.poleN, cnt.Ile
from `table` as t, (SELECT COUNT( *) as `Ile` from `table`) as cnt


zauważ że dałem też * zamiast `pole1` w count, bo się trochę ilość rozjedzie jak w `Pole1` masz Null-a
Artur Świerc

Artur Świerc Programista PHP/Java

Temat: W jaki sposób limitujecie wyniki w stronicowaniu?

Niestety, często jest tak, że klient chce paginację, a w bazie jest milion rekordów. Do tego jeszcze dochodzi duża liczba filtrów dostępnych na stronie. Wtedy każdy użytkownik generuje unikalne zapytanie, cache na nic się nie zda w tym przypadku.

Przeprowadzałem kiedyś porównanie i okazało się, że postgres radzi sobie znacznie szybciej z coutami niż mysql.
Wojciech K.

Wojciech K. realizator pomysłów
własnych

Temat: W jaki sposób limitujecie wyniki w stronicowaniu?

Robert B.:
Pierwsze (dla potrzeb mysql_num_rows()) zawiera wszystkie warunki


count(*) mniejzapycha bufor między PHP a mySQL

ale.....
jeśli pobierasz wszystkie ID, to można od razu zrobić z nich użytek.... czyli w drugim zapytaniu, zamiast stosować znów wszystkie warunki, stosujesz tylko warunek:
WHERE ID in (x,x,x,x,x,x,x,x,x,x,x)

gdzie x to dane wzięte z np. wyników od 50 do 60 z wcześniejszego zapytania (a więc strona szósta)
Tomasz Zadora

Tomasz Zadora programuję

Temat: W jaki sposób limitujecie wyniki w stronicowaniu?

Artur Świerc:
Przeprowadzałem kiedyś porównanie i okazało się, że postgres radzi sobie znacznie szybciej z coutami niż mysql.

Jaki silnik mysql-a, InnoDB czy MyISAM? Podejrzewam, że MyISAM byłoby szybsze niż postgres.

konto usunięte

Temat: W jaki sposób limitujecie wyniki w stronicowaniu?

Wojciech K.:
.... czyli w drugim zapytaniu, zamiast stosować znów wszystkie warunki, stosujesz tylko warunek:
WHERE ID in (x,x,x,x,x,x,x,x,x,x,x)

Hhhm...
Zrobię testy. To co napisałeś może być szybsze choćby ze względu na to, że u mnie wszystkie warunki wykonywane są dwa razy ;)Robert B. edytował(a) ten post dnia 12.09.12 o godzinie 18:10

konto usunięte

Temat: W jaki sposób limitujecie wyniki w stronicowaniu?

Robert B.:
Wojciech K.:
.... czyli w drugim zapytaniu, zamiast stosować znów wszystkie warunki, stosujesz tylko warunek:
WHERE ID in (x,x,x,x,x,x,x,x,x,x,x)

Hhhm...
Zrobię testy. To co napisałeś może być szybsze choćby ze względu na to, że u mnie wszystkie warunki wykonywane są dwa razy ;)

czemu nie użyjesz temporare table?

konto usunięte

Temat: W jaki sposób limitujecie wyniki w stronicowaniu?

Tomasz Zadora:
Artur Świerc:
Przeprowadzałem kiedyś porównanie i okazało się, że postgres radzi sobie znacznie szybciej z coutami niż mysql.

Jaki silnik mysql-a, InnoDB czy MyISAM? Podejrzewam, że MyISAM byłoby szybsze niż postgres.

coś za coś, albo masz spójne dane albo szybki silnik
wybór należy do ciebie
Wojciech K.

Wojciech K. realizator pomysłów
własnych

Temat: W jaki sposób limitujecie wyniki w stronicowaniu?

Robert B.:
Wojciech K.:
.... czyli w drugim zapytaniu, zamiast stosować znów wszystkie warunki, stosujesz tylko warunek:
WHERE ID in (x,x,x,x,x,x,x,x,x,x,x)
Hhhm...
Zrobię testy. To co napisałeś może być szybsze choćby ze względu na to, że u mnie wszystkie warunki wykonywane są dwa razy ;)

dodam jeszcze, że i pierwsze zapytanie możesz "ominąć" (a dokładnie: wykonać je tylko raz - lub ew. ponawiać przy zmianach sortowania) - czyli:
a) przy pierwszym wykonaniu wyszukiwania gromadzisz listę IDków (przy okazji znasz też ich liczbę), generujesz jakiś pseudolosowy identyfikator "wyniku" i zapisujesz to jako element w sesji - jako array, albo string ("1,4,7,3,56,33,67,45,22,787,843,955" itd.) - a zapisujesz jako element dlatego, że user może mieć otwarte kilka okien i przeglądać kilka "wyników" równocześnie - więc każdy musi mieć niezależny identyfikator
b) przy dalszych ruchach odwołujesz się tylko do zapisanego "wyniku" (jego identyfikator przekazując w zmiennych GET/POST) i bierzesz stosowny podzbiór elementów z arraya/stringu - jeśli na stronie jest np. po 5 elementów i jeteś na stronie drugiej, to warunek w zapytaniu pobierającym dane szczegółowe będzie wyglądać: where id IN (33,67,45,22,787)

konto usunięte

Temat: W jaki sposób limitujecie wyniki w stronicowaniu?

Wojciech K.:
...
WHERE ID in (x,x,x,x,x,x,x,x,x,x,x)

Więc...

Odpada ta wersja.

Wszelkie próby zrobienia drugiego zapytania w oparciu o where in spełzły na niczym.

- zapytanie posiada 26 relacji (jest dosyć złożone).
- dla potrzeb stronicowania zapytaniem pierwszym muszę wyjąć ilość rekordów wg warunków
- pobranie wszystkich ID skończyło się wypluciem 35.000 id. Wsadzenie tego do WHERE IN to absurd.
- dodatkowo musiałbym w pierwszym zapytaniu użyć sortowań po to aby ID pojawiły się już w odpowiedniej kolejności - wtedy z poziomu PHP mógłbym wybierać odpowiedni przedział tych pobranych ID po to by do where IN wstawić już tylko wybrane ID ale wtedy sortowania są wykonywane dwa razy a tak tylko raz.

Obecnie ze względu na wielkości tabel i złożoność zapytań nie udało się tego zrealizować ale pobawię się tym pomysłem jeszcze.

konto usunięte

Temat: W jaki sposób limitujecie wyniki w stronicowaniu?

Wojciech K.:
...
dodam jeszcze, że i pierwsze zapytanie możesz "ominąć" (a dokładnie: wykonać je tylko raz - lub ew. ponawiać przy zmianach sortowania)

Nie mogę sobie na to pozwolić. Przy każdej zmianie sortowania muszę mieć uwzględnione zmiany jakie zostały naniesione przez innych. Tak więc ten swoisty cache odpada.Robert B. edytował(a) ten post dnia 13.09.12 o godzinie 00:28
Wojciech K.

Wojciech K. realizator pomysłów
własnych

Temat: W jaki sposób limitujecie wyniki w stronicowaniu?

Robert B.:
- pobranie wszystkich ID skończyło się wypluciem 35.000 id. Wsadzenie tego do WHERE IN to absurd.

wsadzasz tylko tyle ile na jednej stronie.

załóżmy, że masz 10 elementów/stronę - wówczas jeśli jesteś na stronie 8, to do IN (....) bierzesz identyfikatory od [70] do [79]

konto usunięte

Temat: W jaki sposób limitujecie wyniki w stronicowaniu?

Robert B.:
Wojciech K.:
...
dodam jeszcze, że i pierwsze zapytanie możesz "ominąć" (a dokładnie: wykonać je tylko raz - lub ew. ponawiać przy zmianach sortowania)

Nie mogę sobie na to pozwolić. Przy każdej zmianie sortowania muszę mieć uwzględnione zmiany jakie zostały naniesione przez innych. Tak więc ten swoisty cache odpada.

create temporary table tmp_t as
select * from skomplikowane_zapytanie;

SET @ile = (select count(*) as ile from tmp_t);

select tmp_t.* , @ile as ile_rek
from tmp_t;


pisałem TEMPORARY TABLE

odpalasz raz i mas przy każdym rekordzie info o ilości wierszy

toż to proste jak budowa cepa



Wyślij zaproszenie do