webForumDet fria alternativet

Listigt sätt att visa/hantera data...?

PHP

24 svar · 1 363 visningar · startad av learn

Medlem sedan jan. 20051 130 inlägg
Frågan#1

Jag visar en massa data i en lista (tabell) på en hemsida.

Listan kan bland annat sorteras med hjälp av AJAX. På så sätt behöver inte hela sidan laddas om då listan sorteras. Snabbt och snyggt är tanken.

Mitt "problem" är bara det att datan som visas i listan måste hämtas på nytt från databasen varje gång listan sorteras. Det känns inte riktigt rätt. Vad som skulle vara bättre är ifall datan bara hämtas en enda gång och sedan lagra den i en variabel som i sin tur manipuleras varje gång en sortering utförs. Förslagsvis i en session.

Frågeställning:

Är det ett bra sätt, eller hur skulle Du göra? Jag känner en viss oro för prestandan när jag lagrar säg 3000 användare med en massa info kring i en session (som i sin tur lagras på min server). Är den oron befogad?

En annan grej som har med detta att göra. Listan visar 30 rader åt gången och man kan hoppa framåt och bakåt (så som det brukar se ut i vanliga listor/tabeller). Detta sköts också med hjälp av AJAX. Även här hämtas all data på nytt varje gång man "hoppar framåt och bakåt" i listan.

Frågeställning:

All data hämtas (inte bara 30 rader) från databasen. Detta för att jag ska veta hur listan egentligen är och kunna skriva ut "< bakåt | sida 1, sida 2, sida 3 | framåt >". Hur ska jag göra istället? Är det rent prestandamässigt bättre att bara ta reda på antalet rader i databasen och sedan i en separat query hämta 30 rader?

Exempel:

// Hämta antalet
$sql = "
SELECT COUNT(userID) AS antal
FROM users
";

// Hämta 30 användare
$sql = "
SELECT *
FROM users
LIMIT 30
";

Finns det bättre sätt att ta reda på antalet rader? Ett annat problem som jag ser det är att om inte alla rader hämtas så blir det svårt att sortera dem korrekt. Då måste ju själva sorteringen utföras i queryn mot databasen... Och då spricker ju hela konceptet!

Det skulle vara intressant att veta hur andra gör med sina listor, för nästintill alla hemsidor innehåller ju någon form av listor (grids)!

Tack för att Du tagit dig tid att läsa mitt långa inlägg, och hoppas du kan hjälpa mig. :bire

Medlem sedan mars 20034 471 inlägg
#2
  1. Jag kan inte AJAX, så om det finns smarta AJAX-varianter kan jag inte svara på.

Men så länge du ändå hämtar ny data från databasen varje gång har jag svårt (möjligen felaktigt) att se nyttan med att hämta alla 3000 raderna var gång du behöver 30 st. Det låter inte som om du vinner något mot att hämta de rader du behöver direkt från databasen.

Själv använder jag följande Kjellkod ;) (Skrivet av Kjell som startade wF.) OBS! att två rader måste anpassas så de går ihop med dina tabeller.

(Strängt taget använder jag idag en något omarbetad version som lagt all pagingkod i en funktion, vilket underlättar omsortering på olika kolumner, så väl som återanvändning på olika sidor, men jag har inte tillgång till den just nu eftersom jag inte är hemma.)

Medlem sedan nov. 200373 inlägg
#3

Jag skulle definitivt anropa databasen på nytt varje gång användaren byter sida. Du måste ju ändå anropa databasen på nytt om användaren ändrar sorteringen för att få ett nytt resultset, alternativt sortera med php och det är knappast snabbare i stora listor. Bättre att lägga det jobbet på databasen tycker jag, den är ju gjord för sånt.
Du har ju information om sidan de befinner sig på, antal poster per sida och aktuell sortering. Med den infon kan du skapa en sql-fråga som hämtar de 1-30 posterna som ska visas. Du ska aldrig behöva hämta alla poster från databasen någon gång. Det är mycket bättre prestandamässigt att köra med en limit. Nästan alla pagineringsystem jag sett delar upp det i två frågor som du gjort i ditt exempel. Det tar bara några millisekunder att köra count frågan ändå så det skulle jag inte ora mig för.
Men eftersom du använder ajax kan du ju låta pagineringen vara statisk, dvs du skapar den bara varje gång sidan laddas in. Det är ju bara själva listan du vill ladda om så storleken på sökresultatet kan du spara undan nånstans så blir det bara en fråga ändå.

Jag skulle också överväga om sortering "live" är nödvändigt. De flesta sidor tillåter bara sortering innan man söker och vill man ha en annan sortering får man söka igen. Det brukar ju fungera bra för det mesta även om det inte är lika flashigt som ajax :)

...

Du kanske känner till det redan men ett bra sätt att hämta posterna på är nått sånt här:

$page = 3; //aktuell sida
$limit = 30; //max antal poster per sida
$start = ceil( ($page - 1) * $limit);
$sort = "title DESC" //aktuell sortering

SELECT * FROM articles ORDER BY $sort LIMIT $start, $limit

http://www.sitepoint.com/article/perfect-php-pagination/
http://php.about.com/od/mysqlcommands/g/Limit_sql.htm

Medlem sedan jan. 20051 130 inlägg
#4

Stort tack för era svar. Ja, jag kör nog på det alternativet (att hämta aktuella poster t.ex. 1 -30 varje gång sidan laddas om).

Count-queryn går alltså i regel mycket snabbare än en vanlig Select-query?

Medlem sedan jan. 20051 130 inlägg
#5

Synpunkter?

Medlem sedan nov. 200373 inlägg
#6

Synpunkter?
Läs igen vad jag skrev ovan. Spara värdet från din count query efter sökningen så kan du använda det för pagineringen. Då behövs bara en fråga för att hämta posterna varje gång användaren byter sida. Det går snabbare att hämta och gå igenom max 30 poster än alla dina poster varje gång ja :)

Medlem sedan jan. 20051 130 inlägg
#7

Jag hänger med i resonemanget.

Men, nu har jag stött på ett jobbigt problem!

Det blir svårt att sortera listan på det vis som pulse rekommenderar, dvs direkt i sql-queryn, i stället för att sortera den sammansatta arrayen.

Varför?

Jo, om jag hämtar data om användaren från flera olika tabeller i olika querys, t.ex. användardata, loggbok, bilar, hus osv. Datan ska ju visas i samma lista.

Hajar ni problemet?

Om jag t.ex. sorterar efter loggboken (när användaren senast loggade in) så blir ju ordningen fel i de andra... Svårt att förklara på ett enkelt sätt.

Huuur kan man lösa detta? Det känns som att jag i slutänden måste hämta all data varje gång ändå... Trist!

Säg ifrån om ni inte förstår hur jag menar!

Tack :)

Medlem sedan jan. 20051 130 inlägg
#8

Jag skulle ju kunna hämta all data och lagra den i en session... Eller?

Finns det några generella rekommendationer för hur mycket man kan lagra i en php-session?

Medlem sedan jan. 20051 130 inlägg
#9

Jag tror jag ska testa köra på sessioner ändå. Så länge det inte är väldigt prestandakrävande tycker jag det är en mycket bra idé. Då blir det endast en db-query där all data hämtas. Sedan när ajax körs så hämtas datan ur sessionen. Smidigt.

Så, då undrar jag bara över det här med prestandan.

1. Hur mycket kan man lagra i en session?
2. Finns det några rekommendationer?
3. Hur mycket utrymme tar en array uppbyggd enligt följande:

// Datan
$data[] = array("username"=>"alex", "email"=>"alex@olsson.se");
$data[] = array("username"=>"kalle", "email"=>"kalle@kent.se");
$data[] = array("username"=>"olle", "email"=>"olle@abb.se");

// Spara tabellerna som arrayer i en session
$_SESSION["tables"]["test"] = array("headlines"=>"Användarnamn, E-post","data"=>$data);

$_SESSION["tables"] är alltså en tredimensionell(?) array som kan innehålla flera olika tabeller med rubriker och data/rader ($data). $data kommer kunna innehålla flera tusen rader (användare).

4. Kan man räkna ut storleken i bytes på en array enligt ovan? Finns verktyg för detta kanske?

Medlem sedan jan. 20051 130 inlägg
#10

Jag hittade funktionen memory_get_usage()

$temp = memory_get_usage();

for($i=0; $i<2000; $i++)
{
$data[] = array("username"=>"alex", "email"=>"alex@olsson.se");
$data[] = array("username"=>"kalle", "email"=>"kalle@kent.se");
$data[] = array("username"=>"olle", "email"=>"olle@abb.se"); 
}

$_SESSION["tables"]["test"] = array("headlines"=>"Användarnamn, E-post","data"=>$data);

$temp2 = memory_get_usage();

$memory = $temp2 - $temp;

echo round($memory/1048576, 2))." MB";

vilket resulterar i:

2.08 MB

6 000 användare tar alltså i detta fall lite över 2 MB.

Eller har jag fått det om bakfoten?

Medlem sedan jan. 20051 130 inlägg
#11

Ingen som har något att invända?

Medlem sedan jan. 20051 130 inlägg
#12

Jo... någon?

Medlem sedan nov. 200373 inlägg
#13

Förstår inte riktigt hur din sökning är uppbyggd men det låter som du vill visa mycket data och då kan det ju vara svårt att få in allting i en fråga. Har du försökt JOIN:a ihop allting med Sql? Går det inte så är väl sessioner ett bra alternativ antar jag.

Sessioner lagras inte i minnet utan i en katalog på servern som en vanlig fil så du behöver inte oroa dig för att det inte får plats.

memory_get_usage mäter hur mycket minne ditt script förbrukar under en körning och har inget med sessionerna att göra. Däremot kan det ju vara viktigt att hålla koll på ändå.

Medlem sedan mars 20034 471 inlägg
#14

learn skrev:

Om jag t.ex. sorterar efter loggboken (när användaren senast loggade in) så blir ju ordningen fel i de andra... Svårt att förklara på ett enkelt sätt.

Du vet väl att du kan sortera på mer än en kolumn i en SQL-fråga?

Det är ju bara att du bestämmer dig för vad du vill sortera efter och rangordnar det. Tex först på datum något postats i loggboken, senast överst,
sedan anvnamn, A först, sedan bilmärke Ö först:

ORDER BY loggdate DESC, name ASC, carBrand DESC

Till exempel...

(Förutsatt att allt hämtas i en fråga, men annars uppstår väl knappast sorteringsproblemet...?)

Medlem sedan jan. 20051 130 inlägg
#15

aasah skrev:

Du vet väl att du kan sortera på mer än en kolumn i en SQL-fråga?

Det är ju bara att du bestämmer dig för vad du vill sortera efter och rangordnar det. Tex först på datum något postats i loggboken, senast överst,
sedan anvnamn, A först, sedan bilmärke Ö först:

ORDER BY loggdate DESC, name ASC, carBrand DESC

Till exempel...

(Förutsatt att allt hämtas i en fråga, men annars uppstår väl knappast sorteringsproblemet...?)

Tack för tipset. Allt kördes inte i samma fråga förut men nu har jag slagit ihop allt. Lite pilligt med joins hit och dit till en början men nu tycks det fungera...! Jag tror inte längre på sessions-modellen som jag tidigare förespråkat, den känns lite "ful"...

Medlem sedan jan. 20051 130 inlägg
#16

Jag fick inte riktigt svar på min fråga:

learn skrev:

Stort tack för era svar. Ja, jag kör nog på det alternativet (att hämta aktuella poster t.ex. 1 -30 varje gång sidan laddas om).

Count-queryn går alltså i regel mycket snabbare än en vanlig Select-query?

Hur funkar det egentligen, vad är det som gör en fråga långsam. Antalet kolumner som hämtas i SELECT eller antalet rader?

Om jag gör en query för att kolla hur många rader det faktiskt finns:

 // Hämta antalet
$sql = "
SELECT COUNT(userID) AS antal
FROM users
";

...och sedan en query för att hämta de poster som sak visas:

 
// Hämta 30 användare
$sql = "
SELECT *
FROM users
LIMIT 30
";

Vad är då skillnaden i att hämta alla på en gång i stället??

 
// Hämta 30 användare
$sql = "
SELECT *
FROM users
";

Då har jag ju både antalet och mina rader i en fråga...

Ligger "långsamheten" kanske i PHP-scriptet som loopar ut resultatet...

Hmmm... i´m confused...

Snälla förklara för mig. Tack.

Medlem sedan maj 20012 237 inlägg
#17

Om det är data som delas mellan alla användare så kan du kanske lagra datan mha APC.

http://fi2.php.net/apc

Medlem sedan jan. 20051 130 inlägg
#18

jme skrev:

Om det är data som delas mellan alla användare så kan du kanske lagra datan mha APC.

http://fi2.php.net/apc

Njae...

Men någon som kan svara på mina frågor ovan?

Medlem sedan jan. 20051 130 inlägg
#19

Någon som har lust att leda mig in på rätt spår?

Medlem sedan jan. 20051 130 inlägg
#20

Så, hur ska jag tänka?

266 ms totalt · 4 externa anrop · v20260731065814-full.6fe65c25
127 ms — deklarationer (db)
0 ms — hämta statistik (cache)
137 ms — hämta tråd, inlägg och bilagor (db)
125 ms — ändringar (db)