[MySQL] Pagination, infinite scroll en updates

Pagina: 1
Acties:

Vraag


Acties:
  • 0 Henk 'm!

  • Olaf van der Spek
  • Registratie: September 2000
  • Niet online
Ik heb een tabel met items die af en toe geupdate worden. Elk item heeft een primary key (int) en een modified unix timestamp (int).
Hoe selecteer ik de rijen voor pagina 1 en later voor pagina 2, zonder dat updates of deletes in de tussentijd roet in het eten gooien?
Zonder updates is het simpel:
SQL:
1
2
order by modified desc limit 0, 10 # p1
order by modified desc limit 10, 10 # p2

Alhoewel, modified is niet per se uniek dus ook hier kan al iets fout gaan.

Iets als een sequence voor updates zou handig zijn maar volgens mij ondersteunt MySQL dat niet.
Kan het uberhaupt zonder client-side logica?

https://developer.twitter...es/working-with-timelines

[ Voor 3% gewijzigd door Olaf van der Spek op 11-06-2018 09:49 ]

Alle reacties


Acties:
  • 0 Henk 'm!

Verwijderd

Bij het starten van de 'view' de keys opvragen. Dan "select * from where key in (<gedeelte van die keys>)".

Verwijderde items ga je dan uiteraard alsnog niet zien. Enige oplossing daarvoor (aangenomen dat je die wel wilt laten zien) is van te voren alle records opvragen.

[ Voor 44% gewijzigd door Verwijderd op 06-06-2018 16:50 ]


Acties:
  • 0 Henk 'm!

  • Olaf van der Spek
  • Registratie: September 2000
  • Niet online
Verwijderd schreef op woensdag 6 juni 2018 @ 16:44:
Bij het starten van de 'view' de keys opvragen. Dan "select * from where key in (<gedeelte van die keys>)".
Bij 10k of 100k items lijkt mij dat niet zo'n goed plan..

Acties:
  • 0 Henk 'm!

  • Sandor_Clegane
  • Registratie: Januari 2012
  • Niet online

Sandor_Clegane

Fancy plans and pants to match

Is dit wel een probleem?

Als je de sessie ( db connection ) laat bestaan binnen je applicatie dan zullen tussentijdse updates niet getoond worden. Zie: Read Isolation Levels.

Less alienation, more cooperation.


Acties:
  • 0 Henk 'm!

  • DJMaze
  • Registratie: Juni 2002
  • Niet online
Olaf van der Spek schreef op woensdag 6 juni 2018 @ 16:40:
zonder dat updates of deletes in de tussentijd roet in het eten gooien?
Die gooien geen roet in het eten, die zorgen voor de werkelijkheid.

Dat de werkelijkheid anders is dan wat jij wil, dat moet je oplossen.
Je kan bijvoorbeeld ook de id's die je al hebt er uit filteren.
Bijvoorbeeld de eerste 10 zijn: 5, 60, 81, 54, 1, 7, 12, 412, 678, 10
Dan vul je je query aan met:
SQL:
1
AND id NOT IN (5, 60, 81, 54, 1, 7, 12, 412, 678, 10)

Maak je niet druk, dat doet de compressor maar


Acties:
  • 0 Henk 'm!

Verwijderd

Olaf van der Spek schreef op donderdag 7 juni 2018 @ 10:05:
[...]

Bij 10k of 100k items lijkt mij dat niet zo'n goed plan..
Je hebt het over het weergeven van records. Neem aan dat je geen 10-100k records wilt tonen. (Overigens, als je wel 10k records zou willen tonen heb je 40kb data, aangenomen dat je een 32-bit integer hebt als key, dat is prima te doen, zelfs 400kb is geen probleem)

Acties:
  • 0 Henk 'm!

  • Olaf van der Spek
  • Registratie: September 2000
  • Niet online
Ja, het gaat om een JSON API, dus een persistent transactie is geen optie.
Verwijderd schreef op donderdag 7 juni 2018 @ 13:38:
[...]


Je hebt het over het weergeven van records. Neem aan dat je geen 10-100k records wilt tonen. (Overigens, als je wel 10k records zou willen tonen heb je 40kb data, aangenomen dat je een 32-bit integer hebt als key, dat is prima te doen, zelfs 400kb is geen probleem)
In dit geval niet maar ik heb wel views met 700+k items.

[ Voor 51% gewijzigd door Olaf van der Spek op 07-06-2018 15:49 ]


Acties:
  • 0 Henk 'm!

  • Harrie_
  • Registratie: Juli 2003
  • Niet online

Harrie_

⠀                  🔴 🔴 🔴 🔴 🔴

Kun je bij het starten van je view geen current timestamp meegeven en vervolgens met een inner select de modified date overschrijven wanneer deze hoger is dan de initiële timestamp?

SQL:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
SELECT
      id
    , modified
FROM (
    SELECT
          id
        , CASE
              WHEN (modified > @starttime) THEN @starttime
              ELSE modified
          END AS modified
    FROM
    table
) AS data
ORDER BY modified, id DESC


Ik weet niet in hoeverre zo'n constructie werkt in MySQL (ik gebruik tegenwoordig alleen nog maar T-SQL), maar een soortgelijk iets moet toch zeker in MySQL ook wel mogelijk zijn?

Hoeder van het Noord-Meierijse dialect


Acties:
  • +2 Henk 'm!

  • Banpei
  • Registratie: Juli 2001
  • Laatst online: 25-10-2022

Banpei

Hachiroku on this touge?

Over het algemeen is het gebruiken van een offset af te raden: in het begin is het geen probleem, maar bij een image service die ik ooit heb gebouwd kregen we serieuze problemen met duizenden theoretische pagina's en toen kon een query met offset timeouts veroorzaken. Wat MySQL doet bij een offset, is de query uitvoeren, sorteren en alle resultaten tot jouw offset weggooien. :(

Beter is het om alleen een limit te gebruiken en je offset in de where te bepalen. Het is dan wel essentieel om de paginering niet meer met getallen te doen, maar alleen maar dmv volgende en vorige buttons te doen.

Het probleem wat jij nu beschrijft is dat de dataset tussentijds wijzigt en je deze constant wil houden tussen de verschillende calls in. Dit gaat niet omdat de "realiteit" in de database wijzigt. Je kan, zoals hierboven genoemd wordt, de modified date gebruiken om te bepalen van alles dat ouder is dan de selectie die je gemaakt hebt:
code:
1
2
3
4
5
SELECT id, modified
FROM table
WHERE modified < @sometimestamp 
ORDER BY modified DESC 
LIMIT 10

Hierbij selecteer je dan alleen alles dat ouder is dan waar je gebleven bent en limiteer je dit tot 10 rows. Voor de volgende pagina pak je dan als offset de waarde van modifiedb van de laatste rij, en voor de vorige pagina de waarde van modified van de eerste rij.

Als je dan een vorige pagina moet query-en wordt de query als volgt:
code:
1
2
3
4
5
SELECT id, modified
FROM table
WHERE modified > @sometimestamp 
ORDER BY modified ASC 
LIMIT 10

Het nadeel is wel dat als tussentijds een item wijzigt deze je paginering in de war schopt. ;)

Overigens moet je niet vergeten een index te zetten op modified. B)

AE86 gevonden! | So what I thought I'd do was, I'd pretend to be one of those deaf-mutes.


Acties:
  • 0 Henk 'm!

  • DJMaze
  • Registratie: Juni 2002
  • Niet online
Olaf van der Spek schreef op donderdag 7 juni 2018 @ 15:48:
In dit geval niet maar ik heb wel views met 700+k items.
Wie bekijkt er 700.000 items? Bij meer dan 100 raak ik de weg al kwijt en wil ik kunnen filteren.

[ Voor 4% gewijzigd door DJMaze op 08-06-2018 15:16 ]

Maak je niet druk, dat doet de compressor maar


Acties:
  • 0 Henk 'm!

  • Olaf van der Spek
  • Registratie: September 2000
  • Niet online
DJMaze schreef op vrijdag 8 juni 2018 @ 15:15:
[...]

Wie bekijkt er 700.000 items? Bij meer dan 100 raak ik de weg al kwijt en wil ik kunnen filteren.
Filteren en zoeken kan natuurlijk..

Acties:
  • 0 Henk 'm!

  • Olaf van der Spek
  • Registratie: September 2000
  • Niet online
Banpei schreef op vrijdag 8 juni 2018 @ 14:37:
Over het algemeen is het gebruiken van een offset af te raden: in het begin is het geen probleem, maar bij een image service die ik ooit heb gebouwd kregen we serieuze problemen met duizenden theoretische pagina's en toen kon een query met offset timeouts veroorzaken. Wat MySQL doet bij een offset, is de query uitvoeren, sorteren en alle resultaten tot jouw offset weggooien. :(
Bekend probleem, is dat nog steeds niet opgelost?
Het probleem wat jij nu beschrijft is dat de dataset tussentijds wijzigt en je deze constant wil houden tussen de verschillende calls in. Dit gaat niet omdat de "realiteit" in de database wijzigt. Je kan, zoals hierboven genoemd wordt, de modified date gebruiken om te bepalen van alles dat ouder is dan de selectie die je gemaakt hebt:
code:
1
2
3
4
5
SELECT id, modified
FROM table
WHERE modified < @sometimestamp 
ORDER BY modified DESC 
LIMIT 10
Bij meerdere rows met dezelfde modified waarde gaat dit fout, je moet dan zowel in de where als order by <modified, id> gebruiken denk ik.

Acties:
  • 0 Henk 'm!

  • Banpei
  • Registratie: Juli 2001
  • Laatst online: 25-10-2022

Banpei

Hachiroku on this touge?

Olaf van der Spek schreef op vrijdag 8 juni 2018 @ 15:53:
Bekend probleem, is dat nog steeds niet opgelost?
Nope. In bijna elk RDBMS bestaat dit probleem omdat ze nog steeds een offset functie in de taal hebben... Dus zodra die er uit is, is het probleem opgelost! :D
Olaf van der Spek schreef op vrijdag 8 juni 2018 @ 15:53:
Bij meerdere rows met dezelfde modified waarde gaat dit fout, je moet dan zowel in de where als order by <modified, id> gebruiken denk ik.
Klopt. Ik ben voor de eenvoudigheid er vanuit gegaan dat je redelijk uniek zou zijn met de modified waardes. Het wordt iets gecompliceerder: je krijgt dan te maken met dat je geen ids kunt gebruiken in de where. Immers kunnen items geupdate worden en dus in een andere volgorde staan dan de ids. Dus je kunt dan geen dubbele range scan doen.

Misschien is de simpelste oplossing dan niet een INSERT INTO ... ON DUPLICATE UPDATE / UPDATE te doen, maar standaard een REPLACE INTO te gebruiken. Dit zorgt er voor dat er altijd een nieuw record geinsert wordt en de ids veranderen bij een wijziging. Maar dat geeft weer andere problemen, bijvoorbeeld als de ids gelinkt zijn aan een gebruiker oid. :|

AE86 gevonden! | So what I thought I'd do was, I'd pretend to be one of those deaf-mutes.


Acties:
  • 0 Henk 'm!

  • drm
  • Registratie: Februari 2001
  • Laatst online: 09-06 13:31

drm

f0pc0dert

Ik zou zeggen dat het veel makkelijker is om de gebruiker op de hoogte te stellen dat ze naar een outdated view aan het kijken zijn. Dat is precies wat @DJMaze al zegt, de werkelijkheid. Waarom zou je die verstoppen?

Music is the pleasure the human mind experiences from counting without being aware that it is counting
~ Gottfried Leibniz


Acties:
  • 0 Henk 'm!

  • CurlyMo
  • Registratie: Februari 2011
  • Laatst online: 14:34
Olaf van der Spek schreef op woensdag 6 juni 2018 @ 16:40:
Iets als een sequence voor updates zou handig zijn maar volgens mij ondersteunt MySQL dat niet.
Kan het uberhaupt zonder client-side logica?
Het kan prima in je database, maar het vergt wel een hele andere denkwijze. Je moet je database namelijk met behoud van historie opbouwen. Idealiter zijn daarin updates niet toegestaan en deletes verboden, maar gebeurt alles (zoveel mogelijk) via inserts.

Je hebt dan naast je standaard data als metadata een PK, valid, modified

code:
1
2
3
1   aap     01-01-2017      01-01-2017
2   noot    01-01-2017      01-02-2017
3   mies    01-03-2017      01-03-2017

Stel iemand is op 28 februari 2017 om 23:59 naar je lijst aan het kijken en er komt op 1 maart 2017 een update binnen, dan kan je alsnog de laatste situatie opvragen op 28 februari 2018.

Dus de situatie vóór 1 maart over januari is noot, de situatie vóór 1 februari over januari is aap, de situatie op of na 1 maart is mies.

De valid datum geeft aan welk gegeven wordt overruled door een ander gegeven, de modified datum geeft aan vanaf wanneer dat de nieuwe waarheid is geworden.

Je ziet in het veld ook wel tijdvakken gebruikt worden. Dan wordt aangegeven vanaf wanneer tot wanneer een bepaald gegeven waarheid is. Alleen moet je wel weer in updates vervallen om rijen inactief te maken. Ik vind het prettiger om in deze situaties alleen inserts toe te staan.

Je moet echter wel een heel specifiek doel hebben om een database schema op deze manier op te bouwen, want het is vrij lastig om goed te modelleren en onderhouden. Je tabellen kunnen ook snel groeien afhankelijk van de snelheid waarmee gegevens worden bijgewerkt.

Sinds de 2 dagen regel reageer ik hier niet meer


Acties:
  • 0 Henk 'm!

  • DJMaze
  • Registratie: Juni 2002
  • Niet online
@CurlyMo je bedoelt gewoon een revisie systeem ;)

Bijvoorbeeld:
SQL:
1
2
3
4
5
6
7
8
9
10
11
CREATE TABLE posts (
    post_id SERIAL,
    post_time_created INT,
    post_time_last_modified INT
);

CREATE TABLE posts_revisions (
    post_id INT,
    post_revision_time_created INT,
    post_revision_data LONGTEXT
);


Hierbij zit je wel weer met het probleem dat je niet alle revisies moet ophalen <= TIMESTAMP.
Je krijgt dus iets als:
SQL:
1
2
3
4
5
6
SELECT *
FROM posts_revisions r
WHERE post_revision_time_created = (SELECT
    MAX(post_revision_time_created)
    FROM posts_revisions AS rl
    WHERE rl.post_id = r.post_id AND post_revision_time_created <= TIMESTAMP)

[ Voor 89% gewijzigd door DJMaze op 09-06-2018 14:17 ]

Maak je niet druk, dat doet de compressor maar


Acties:
  • 0 Henk 'm!

  • CurlyMo
  • Registratie: Februari 2011
  • Laatst online: 14:34
DJMaze schreef op zaterdag 9 juni 2018 @ 14:08:
@CurlyMo je bedoelt gewoon een revisie systeem ;)

Bijvoorbeeld:
SQL:
1
2
3
4
5
6
7
8
9
10
11
CREATE TABLE posts (
    post_id SERIAL,
    post_time_created INT,
    post_time_last_modified INT
);

CREATE TABLE posts_revisions (
    post_id INT,
    post_revision_time_created INT,
    post_revision_data LONGTEXT
);


Hierbij zit je wel weer met het probleem dat je niet alle revisies moet ophalen <= TIMESTAMP.
Je krijgt dus iets als:
SQL:
1
2
3
4
5
6
SELECT *
FROM posts_revisions r
WHERE post_revision_time_created = (SELECT
    MAX(post_revision_time_created)
    FROM posts_revisions AS rl
    WHERE rl.post_id = r.post_id AND post_revision_time_created <= TIMESTAMP)
Volgens mij is de selectie simpelweg (pseudocode):
SQL:
1
2
3
4
5
6
7
8
9
10
select
    distinct waarde
from
    tabel
where
    valid <= '2017-02-01'
and
    modified <= '2017-03-01'
and
    entity_id = 1


Revision model ken ik niet, maar ik vind het in ieder geval logisch genoeg om zelf te kunnen bedenken :)

Sinds de 2 dagen regel reageer ik hier niet meer


Acties:
  • 0 Henk 'm!

  • DJMaze
  • Registratie: Juni 2002
  • Niet online
@CurlyMo Ah zo bedoel je. Een soort history log (zonder data revisies).
Zeg maar:
SQL:
1
2
3
4
5
SELECT DISTINCT entity_id
FROM changes_log
WHERE change_datetime < TIMESTAMP
ORDER BY change_datetime DESC
LIMIT 10 OFFSET 0

Dan weet je welke items je moet tonen.
Je ziet dan wel de "nieuwste" versie, maar op basis van een oude tijd.

[ Voor 31% gewijzigd door DJMaze op 09-06-2018 14:48 ]

Maak je niet druk, dat doet de compressor maar


Acties:
  • 0 Henk 'm!

  • CurlyMo
  • Registratie: Februari 2011
  • Laatst online: 14:34
DJMaze schreef op zaterdag 9 juni 2018 @ 14:41:
@CurlyMo Ah zo bedoel je. Een soort history log (zonder data revisies).
Zeg maar:
code:
1
2
3
4
5
SELECT DISTINCT entity_id
FROM changes_log
WHERE change_datetime < TIMESTAMP
ORDER BY change_datetime DESC
LIMIT 10 OFFSET 0


Dan weet je welke items je moet tonen.
Je ziet dan wel de "nieuwste" versie, maar op basis van een oude tijd.
Precies, maar het kunnen selecteren op valid is net zo belangrijk.

Het probleem met insert only database model implementaties die ik lees op internet is dat ze toch met tijdvakken werken. Hierdoor ben je alsnog de einddatum van het vorige record aan het updaten en die moet dan synchroon zijn met de begindatum van het volgende record. Daarmee is het niet insert only en foutgevoelig.

Als het gaat om bijv. reacties dan is er maar één versie van een reactie op een bepaald moment geldig. Zoals hier op het forum. Ik kan eindeloos mijn reactie aanpassen, maar zie alleen de laatste versie van een bepaald moment. Dan kan je gewoon prima één tabel hebben met twee datum meta velden.

Maar het kan ook zo zijn dat er meerdere combinaties tegelijk geldig kunnen zijn zoals iemands nationaliteit. Dan heb je wel twee tabellen nodig om insert only te blijven.
SQL:
1
2
3
4
5
6
7
8
9
10
11
12
13
create table person_nationality (
    id serial,
    person_id bigint,
    nationality_id int
);

create table person_nationality_cycle (
    id serial,
    person_nationality_id references person_nationality(person_id),
    status boolean,
    valid datetime,
    modified datetime
);

[ Voor 5% gewijzigd door CurlyMo op 09-06-2018 14:51 ]

Sinds de 2 dagen regel reageer ik hier niet meer


Acties:
  • 0 Henk 'm!

  • P.O. Box
  • Registratie: Augustus 2005
  • Niet online
Ik heb het vermoeden dat het probleem van de TS meer zit in het feit dat de gebruiker/webservice een request doet van de 1e 100 items en dan bij het opvragen van de volgende pagina item 101 t/m 200 moet krijgen, maar dat door sortering van het resultaat er wel eens een verspringing kan hebben plaatsgevonden waardoor bijvoorbeeld item 110 bij een nieuwe opvraging door sortering op postiie 90 terecht komt. Gevolg is dat je dan op pagina 2 item 100 t/m 200 krijgt , uitgezonderd 110, ipv 101 t/m 200.

Ik weet niet of het de beste oplossing is, maar wellicht een idee:
Bij de eerste request creer je een temporary table met een autoincrement veld en een id veld. Dat is twee kolommetjes, dus waarschijnlijk ook bij grote hoeveelheden data nog wel snel. Daarna ga je, zodra pagina > 1 wordt opgevraagd, je tijdelijke tabel raadplegen gejoined op je originele tabel met autoincrementveld > 100, en daarna > 200, etc etc. Aan het einde moet je dan nog even bedenken wat je doet met "ondertussen nieuw ingevoegde data", maar dat is heel erg afhankelijk van hoe je dat zelf verwacht, je kan die bijv. ook gewoon negeren.
Ik weet niet of in je omgeving de database connectie openhoudt tussen requests. Indien dat niet het geval is kun je ook een minder tijdelijke tabel met een unieke naam aanmaken en die tabelen eens in de x tijd weggooien.

[ Voor 3% gewijzigd door P.O. Box op 10-06-2018 10:28 ]


Acties:
  • 0 Henk 'm!

  • Harrie_
  • Registratie: Juli 2003
  • Niet online

Harrie_

⠀                  🔴 🔴 🔴 🔴 🔴

En wat is er dan mis met deze oplossing? Volgens mij adresseert dat exact probleem van TS?

Hoeder van het Noord-Meierijse dialect


Acties:
  • 0 Henk 'm!

  • CurlyMo
  • Registratie: Februari 2011
  • Laatst online: 14:34
Harrie_ schreef op zondag 10 juni 2018 @ 12:43:
En wat is er dan mis met deze oplossing? Volgens mij adresseert dat exact probleem van TS?
Nog los van of het het antwoord is op de vraag van TS, waarom doe je het niet zo:
SQL:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
SELECT
    id,
    CASE
        WHEN (modified > @starttime) THEN @starttime
        ELSE modified
    END AS modified
FROM
    table
ORDER BY
    CASE
        WHEN (modified > @starttime) THEN @starttime
        ELSE modified
    END,
    id DESC

Dat scheelt weer een inline view.

Nog makkelijker is:
SQL:
1
2
3
4
5
6
7
SELECT
    id,
    LEAST(modified, @starttime) AS modified
FROM
    table
ORDER BY
    LEAST(modified, @starttime), id DESC

[ Voor 11% gewijzigd door CurlyMo op 10-06-2018 16:36 ]

Sinds de 2 dagen regel reageer ik hier niet meer


Acties:
  • 0 Henk 'm!

  • frickY
  • Registratie: Juli 2001
  • Laatst online: 14:10
Onthoud het timestamp waarop je pagina 1 hebt opgehaald. Daarna ?page=2&ts=102829382.
Vervolgens alleen items selecteren met een lagere timestamp

Acties:
  • +2 Henk 'm!

  • CurlyMo
  • Registratie: Februari 2011
  • Laatst online: 14:34
frickY schreef op zondag 10 juni 2018 @ 16:35:
Onthoud het timestamp waarop je pagina 1 hebt opgehaald. Daarna ?page=2&ts=102829382.
Vervolgens alleen items selecteren met een lagere timestamp
Dat werkt niet.

Als je items 0 t/m 100 selecteert en de modified timestamp van record 50 veranderd naar later, dan is je oorspronkelijke selectie 0 t/m 49 + 51 t/m 101 geworden, aangezien record 50 niet meer voor je selectiedatum valt.

Een soortgelijk probleem is er aan de hand met de oplossing van @Harrie_. Alleen is nu de impact dat je oorspronkelijke sortering veranderd. Record 50 verplaatst zich nu naar het eind van de sortering.

[ Voor 18% gewijzigd door CurlyMo op 10-06-2018 16:41 ]

Sinds de 2 dagen regel reageer ik hier niet meer


Acties:
  • 0 Henk 'm!

  • frickY
  • Registratie: Juli 2001
  • Laatst online: 14:10
Dat klopt, maar dat is de enige manier hoe ts zoiets voor elkaar kan krijgen

Acties:
  • 0 Henk 'm!

  • CurlyMo
  • Registratie: Februari 2011
  • Laatst online: 14:34
frickY schreef op zondag 10 juni 2018 @ 17:43:
Dat klopt, maar dat is de enige manier hoe ts zoiets voor elkaar kan krijgen
Als je de voorbeelden van @DJMaze en mij hebt bekeken dan zie je dat wel degelijk ook anders kan.

Sinds de 2 dagen regel reageer ik hier niet meer


Acties:
  • 0 Henk 'm!

  • frickY
  • Registratie: Juli 2001
  • Laatst online: 14:10
Die komen met een behoorlijke performance penalty

Acties:
  • +1 Henk 'm!

  • CurlyMo
  • Registratie: Februari 2011
  • Laatst online: 14:34
frickY schreef op zondag 10 juni 2018 @ 17:49:
Die komen met een behoorlijke performance penalty
Dat hangt van de implementatie en eisen af, maar die specificaties worden door @Olaf van der Spek niet gesteld. Als die updates marginaal gebeuren, terwijl de sortering kritisch is voor zijn proces dan maakt het nauwelijks iets uit.

Sinds de 2 dagen regel reageer ik hier niet meer


Acties:
  • 0 Henk 'm!

  • DJMaze
  • Registratie: Juni 2002
  • Niet online
frickY schreef op zondag 10 juni 2018 @ 17:49:
Die komen met een behoorlijke performance penalty
Wat is "behoorlijk"?
Ik ontwikkel websites op die manier, en de query is 1.000x sneller dan die van WordPress.
De pagina laad in 40ms en WordPress in 300ms.
Oftewel, de query is pas een probleem als de rest snel is. Als de rest langzaam is kan je beter eerst daar naar kijken, dan discussieren over onze oplossingen ;)

Maak je niet druk, dat doet de compressor maar


Acties:
  • 0 Henk 'm!

  • GlowMouse
  • Registratie: November 2002
  • Niet online
Er valt geen goed antwoord te geven zonder meer te weten over het aantal pagina's, het aantal updates, het aantal gebruikers, en de verwachte performance.

Bij de eerste oplossing van DJMaze (met NOT IN) moet je die lijst op de client of server bijhouden, en dat is niet ideaal bij een groot aantal gebruikers of pagina's. Bovendien is NOT IN niet zo efficiënt (opzoeken in de NOT-IN lijst gebeurt lineair).

De oplossing van Harrie_ sorteert op de uitkomst van een CASE, waarbij een index niet kan helpen. Bovendien komen alle gewijzigde records bovenaan te staan.

CurlyMo heeft vermoedelijk de beste oplossing, maar zijn implementatie is niet zo goed qua indices.

Acties:
  • 0 Henk 'm!

  • DJMaze
  • Registratie: Juni 2002
  • Niet online
@GlowMouse klopt, de NOT IN is onhandig om meerdere redenen.
Maar goed, @Olaf van der Spek heeft niet echt de details prijsgegeven omtrent de structuur waar hij mee moet werken en of hij deze kan aanpassen.

Maak je niet druk, dat doet de compressor maar


Acties:
  • 0 Henk 'm!

  • Harrie_
  • Registratie: Juli 2003
  • Niet online

Harrie_

⠀                  🔴 🔴 🔴 🔴 🔴

CurlyMo schreef op zondag 10 juni 2018 @ 16:38:
[...]

Dat werkt niet.

Als je items 0 t/m 100 selecteert en de modified timestamp van record 50 veranderd naar later, dan is je oorspronkelijke selectie 0 t/m 49 + 51 t/m 101 geworden, aangezien record 50 niet meer voor je selectiedatum valt.

Een soortgelijk probleem is er aan de hand met de oplossing van @Harrie_. Alleen is nu de impact dat je oorspronkelijke sortering veranderd. Record 50 verplaatst zich nu naar het eind van de sortering.
Volgens mij bedoelt @frickY (en dat bedoel ik dus ook) dat je de intiële timestamp van pagina 1 onthoudt, die verandert daarna dus niet meer. Ik zie niet in hoe dat je oorspronkelijke dataset / sorting wijzigt?

Hoeder van het Noord-Meierijse dialect


Acties:
  • +1 Henk 'm!

  • CurlyMo
  • Registratie: Februari 2011
  • Laatst online: 14:34
Harrie_ schreef op zondag 10 juni 2018 @ 20:54:
[...]


Volgens mij bedoelt @frickY (en dat bedoel ik dus ook) dat je de intiële timestamp van pagina 1 onthoudt, die verandert daarna dus niet meer. Ik zie niet in hoe dat je oorspronkelijke dataset / sorting wijzigt?
Dat snap ik wel, maar de onderliggende data kan wel veranderen tijdens je sessie.

Sinds de 2 dagen regel reageer ik hier niet meer


Acties:
  • 0 Henk 'm!

  • Olaf van der Spek
  • Registratie: September 2000
  • Niet online
Harrie_ schreef op donderdag 7 juni 2018 @ 16:10:
Kun je bij het starten van je view geen current timestamp meegeven en vervolgens met een inner select de modified date overschrijven wanneer deze hoger is dan de initiële timestamp?

SQL:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
SELECT
      id
    , modified
FROM (
    SELECT
          id
        , CASE
              WHEN (modified > @starttime) THEN @starttime
              ELSE modified
          END AS modified
    FROM
    table
) AS data
ORDER BY modified, id DESC


Ik weet niet in hoeverre zo'n constructie werkt in MySQL (ik gebruik tegenwoordig alleen nog maar T-SQL), maar een soortgelijk iets moet toch zeker in MySQL ook wel mogelijk zijn?
Heeft T-SQL geen least functie?
Oeps CurlyMo was mij voor.

MySQL:
1
select id, least(modified, @starttime) mo from topics order by mo desc limit 10


Dit lost volgens mij echter niks op..
drm schreef op zaterdag 9 juni 2018 @ 11:44:
Ik zou zeggen dat het veel makkelijker is om de gebruiker op de hoogte te stellen dat ze naar een outdated view aan het kijken zijn. Dat is precies wat @DJMaze al zegt, de werkelijkheid. Waarom zou je die verstoppen?
Kan, maar dan moet je dus de data zoals die was tijdens het eerste request kunnen reproduceren.. weet niet of dat een simpeler probleem is.
DJMaze schreef op zondag 10 juni 2018 @ 19:49:
@GlowMouse klopt, de NOT IN is onhandig om meerdere redenen.
Maar goed, @Olaf van der Spek heeft niet echt de details prijsgegeven omtrent de structuur waar hij mee moet werken en of hij deze kan aanpassen.
De structuur kan aangepast worden.

[ Voor 31% gewijzigd door Olaf van der Spek op 11-06-2018 10:07 ]


Acties:
  • 0 Henk 'm!

  • DePruus
  • Registratie: Januari 2017
  • Laatst online: 11:00
Het probleem blijft echter bestaan als een gebruiker data opvraagt en vervolgens niet bladert. Dan kunnen tussen zijn getoonde records inmiddels deleted exemplaren zitten en nieuwe toevoegingen worden niet getoond. Je zou kunnen overwegen om elke x seconden de query opnieuw uit te voeren. Dan verandert voor de gebruiker telkens het scherm, een reload van data.

Acties:
  • 0 Henk 'm!

  • CurlyMo
  • Registratie: Februari 2011
  • Laatst online: 14:34
Olaf van der Spek schreef op maandag 11 juni 2018 @ 09:45:
[...]
Dit lost volgens mij echter niks op.
Kan je iets meer duidelijkheid geven over het doel en de specificaties van de vereiste implementatie, want je hebt volgens mij voldoende oplossingsrichtingen gekregen. Om vervolgens mee te denken wat past bij jou situatie hebben we die aanvullende informatie nodig.

Sinds de 2 dagen regel reageer ik hier niet meer


Acties:
  • 0 Henk 'm!

  • Sandor_Clegane
  • Registratie: Januari 2012
  • Niet online

Sandor_Clegane

Fancy plans and pants to match

Als je de mogelijkheid hebt en je kan een sessie bijhouden op je api, dan zou je een DB cursor kunnen gebruiken. Voor de hoeveelheid items misschien wel zwaar, maar dat zou je kunnen testen.

Ben je wel van alle geneuzel qua tussentijdse updates e.d. af.

Less alienation, more cooperation.


Acties:
  • 0 Henk 'm!

  • CurlyMo
  • Registratie: Februari 2011
  • Laatst online: 14:34
Sandor_Clegane schreef op maandag 11 juni 2018 @ 11:53:
Als je de mogelijkheid hebt en je kan een sessie bijhouden op je api, dan zou je een DB cursor kunnen gebruiken. Voor de hoeveelheid items misschien wel zwaar, maar dat zou je kunnen testen.

Ben je wel van alle geneuzel qua tussentijdse updates e.d. af.
Voorkomt dat ook gedoe met tussentijdse updates van daadwerkelijk data in je database?

Sinds de 2 dagen regel reageer ik hier niet meer


Acties:
  • 0 Henk 'm!

  • Sandor_Clegane
  • Registratie: Januari 2012
  • Niet online

Sandor_Clegane

Fancy plans and pants to match

CurlyMo schreef op maandag 11 juni 2018 @ 12:01:
[...]

Voorkomt dat ook gedoe met tussentijdse updates van daadwerkelijk data in je database?
In principe neem je een snapshot, vraag is alleen hoe zwaar het is. Als het goed is gebruik je dan de read level isolation van je DB om dat te voorkomen.

Het is wel wat werk, je moet het ook in een transactie weten te zetten. Maar er is niet een silver bullet qua pagination ben ik wel achter.

Misschien kun je ook een materialized view maken die je standaard om de zoveel tijd ververst als er geen readers zijn, ik noem maar wat.

Less alienation, more cooperation.


Acties:
  • 0 Henk 'm!

  • DJMaze
  • Registratie: Juni 2002
  • Niet online
Sandor_Clegane schreef op maandag 11 juni 2018 @ 12:17:
In principe neem je een snapshot, vraag is alleen hoe zwaar het is. Als het goed is gebruik je dan de read level isolation van je DB om dat te voorkomen.
Ehm.. @CurlyMo en ik hebben al aangegeven dat dit dus niet hoeft.

Maak je niet druk, dat doet de compressor maar


Acties:
  • 0 Henk 'm!

  • drm
  • Registratie: Februari 2001
  • Laatst online: 09-06 13:31

drm

f0pc0dert

Olaf van der Spek:
Kan, maar dan moet je dus de data zoals die was tijdens het eerste request kunnen reproduceren.. weet niet of dat een simpeler probleem is.
Als je dit puur op timestamps baseert is het niet zo ingewikkeld. Het kost je een extra query, maar wel een erg goedkope.

Music is the pleasure the human mind experiences from counting without being aware that it is counting
~ Gottfried Leibniz


Acties:
  • +1 Henk 'm!

  • CurlyMo
  • Registratie: Februari 2011
  • Laatst online: 14:34
drm schreef op maandag 18 juni 2018 @ 19:05:
[...]
Als je dit puur op timestamps baseert is het niet zo ingewikkeld. Het kost je een extra query, maar wel een erg goedkope.
DJMaze schreef op maandag 11 juni 2018 @ 14:55:
[...]

Ehm.. @CurlyMo en ik hebben al aangegeven dat dit dus niet hoeft.

Sinds de 2 dagen regel reageer ik hier niet meer

Pagina: 1