Helt klart är det bästa att låta MS ta hand om din Paging. Din version är dock ett mycket dåligt exempel på hur man kan göra det. Ut på nätet och sök så hittar du bättre lösningar.
- magnus
10 svar · 631 visningar · startad av joup
Hej,
Jag har en fråga om paging med ASP/VBScript och en MS SQL Server-databas. Vad jag vet finns det bara två olika sätt att fixa paging, och jag undrar helt enkelt vilket som är bäst.
1. Man använder paging-metoden i ASP. Exempel:
pagesize = request("sidstorlek")
pagenumber = request("sidnummer")
if pagesize = "" then
pagesize = 30
else
pagesize = request("sidstorlek")
end if
if pagenumber = "" then
pagenumber = 1
else
pagenumber = request("sidnummer")
end if
pagenumber=Cint(pagenumber)
pagesize=Cint(pagesize)
SQL = "SELECT * from nyheter Order by id desc"
Set RS = Server.CreateObject("ADODB.Recordset")
RS.cursorlocation=aduseclient
RS.cachesize=5
RS.CursorType = 1
RS.PageSize = pagesize
RS.Open SQL, Connection
pagecount = RS.PageCount
RS.AbsolutePage = pagenumber
antal = 1
while antal <= pagesize and not RS.EOF
2. Man använder subqueries i SQL-satsen. Exempel:
SELECT TOP 39 spel.id, spel.live, spel.uppdaterad, spel.namn, spel.release_type, spel.release AS datum, spel.spelare, spel.genre FROM spel where id not in (select top " & visar & " id from spel where release>'" & now-5 & "' order by release, release_type, namn) AND release>'" & now-5 & "' ORDER BY release, release_type, namn
Nu till själva frågan. Om man har en väldigt belastad hemsida (många besökare), vilken av dessa två metoder är bäst när det kommer till att dela upp en diskussionsforum i flera olika sidor, rent prestandamässigt? Tänk att tabellen har ungefär 100.000-200.000 poster.
Som jag ser det verkar båda metoderna ha nackdelar som kan vara dåliga för prestandan. Alternativ 1 så hämtar man ju hela tabellen med SQL-kommandot (ingen begränsning med top-kommando) vilket inte kan vara bra. Alternativ 2 så använder man ju subqueries, som kanske inte är så bra heller?
Någon som har någon erfarenhet av dessa metoder, och vet vilken som är snabbast/effektivast för en stor tabell som dessutom är hårt belastad?
Helt klart är det bästa att låta MS ta hand om din Paging. Din version är dock ett mycket dåligt exempel på hur man kan göra det. Ut på nätet och sök så hittar du bättre lösningar.
- magnus
Problemet med GetRows() i detta exempel, är att du skickar alla information från databasen till webservern och lägger detta i recordsetet.
Om du då har 1 miljon rader i databas, så blir det en del data som måste skickas för att visa 10 rader.
- magnus
Gladh skrev:
Problemet med GetRows() i detta exempel, är att du skickar alla information från databasen till webservern och lägger detta i recordsetet.
Om du då har 1 miljon rader i databas, så blir det en del data som måste skickas för att visa 10 rader.
- magnus
Det var intressant :)
Och hur ska man få till en bättre lösning?
Så att recordsetet endast innehåller de poster som man ska visa?
Byt till MySQL/Postgresql och använd LIMIT ;)
Byt till MySQL/Postgresql och använd LIMIT
Eller Oracle och använd ROWNUM.
Vill du göra det i SQL Server så använd dig av en lösning med SP. Men som sagts innan, ut på google och sök på SQL Server, SP och Paging. Så kommer du hitta massor med lösningar, vissa bra och andra mindre bra.
- Magnus
Hittade faktiskt en lösning igår när jag sökte runt lite på webben som jag implementerat på min hemsida, och som jag faktiskt tycker har fått upp prestandan en del (jag körde med alt. 2 tidigare).
Man använder sig av en Stored Procedure som ser ut så här:
CREATE PROCEDURE "ForumPaging"
@Page int,
@Size int,
@forumid int
AS
DECLARE @Start int, @End int
BEGIN TRANSACTION GetDataSet
SET @Start = (((@Page - 1) * @Size) + 1)
IF @@ERROR <> 0
GOTO ErrorHandler
SET @End = (@Start + @Size - 1)
IF @@ERROR <> 0
GOTO ErrorHandler
CREATE TABLE #TemporaryTable
(
Row int IDENTITY(1,1) PRIMARY KEY,
prio int,
originalid int,
kopia int,
senastav varchar(25),
typ int,
id int,
forumid int,
amne varchar(100),
av int,
namn varchar(25),
senaste datetime,
AntSvar int,
Sidor int,
stangd int,
meddelande varchar(200)
)
IF @@ERROR <> 0
GOTO ErrorHandler
INSERT INTO #TemporaryTable
SELECT forum.prio, forum.originalid, forum.kopia, forum.senastav, forum.typ, forum.id, forum.forumid, forum.amne, forum.av, forum.namn, forum.senaste, COUNT(f2.id) AS AntSvar, COUNT(f2.id)/40 AS Sidor, forum.stangd, CAST(forum.meddelande as VARCHAR(200)) as meddelande FROM forum LEFT JOIN forum as f2 ON forum.id = f2.svarsid WHERE forum.original=1 and forum.forumid = @forumid GROUP BY forum.id, forum.prio, forum.originalid, forum.kopia, forum.senastav, forum.typ, forum.id, forum.forumid, forum.amne, forum.av, forum.namn, forum.senaste, forum.stangd, CAST(forum.meddelande AS VARCHAR(200)) ORDER BY forum.prio desc, forum.senaste desc
IF @@ERROR <> 0
GOTO ErrorHandler
SELECT prio, originalid, kopia, senastav, typ, id, forumid, amne, av, namn, senaste, AntSvar, Sidor, stangd, meddelande
FROM #TemporaryTable
WHERE (Row >= @Start) AND (Row <= @End)
IF @@ERROR <> 0
GOTO ErrorHandler
DROP TABLE #TemporaryTable
COMMIT TRANSACTION GetDataSet
RETURN 0
ErrorHandler:
ROLLBACK TRANSACTION GetDataSet
RETURN @@ERROR
Är detta en bra/bättre lösning? Eller finns det vassare ändå?
Bör även tillägga att byta databas till MySQL eller något annat inte är ett alternativ. Jag har precis bytt från MySQL (eftersom det buggade rätt friskt under Win 2003) till MSSQL, och jag tänker inte byta tillbaka. :)
klicka på länken i mitt sista inlägg! :)
http://www.webforum.nu/showthread.php?s=&forumid=53&threadid=92823
Förresten, hur skall man anropa en SP "bäst" i ASP?
Just nu kör jag bara med
SQL = "EXEC Paging @Page=" & sida & ", @Size=31, @forumid=" & forumid
Set RS = Connection.Execute(SQL)
Är detta bra, eller finns det bättre/snabbare sätt att anropa en SP?
joup skrev:
Set RS = Connection.Execute(SQL)
Du får ganska osnabba inställningar när du gör så där...
dim rstPage
Set rstPage = Server.CreateObject("ADODB.Recordset")
With rstPage
.CursorLocation = 3 ' adUseClient
.Open "EXEC sp_name", myConnection,0,1
End With
Så där minskar du ned på databasens ansträngning. 0,1 är readonly, forwardonly eller nåt sånt, en s k firehose cursor blir det iaf. Den här koden är väldigt testad. En sak att tänka på är att om du har ett recordset öppet måste du skapa en ny connection för recordset nummer 2, eller i min kod öppna med connection-strängen där det står myConnection i stället för ett connection-objekt. Gör man inte det så blir det en server-cursor på #2 och då körs det sp_cursorfetch-procedurer i SQL servern som försämrar prestanda märkbart. I fall målet är att lätta upp för SQL Servern så är denna kod att rekommendera som sagt.