Zware query van +36.000 rows printen

Overzicht Reageren

Sponsored by: Vacatures door Monsterboard

Pagina: 1 2 volgende »

Joni Fleischer
Moderator

Joni Fleischer

09/06/2015 21:43:38
Quote Anchor link
Hallo allemaal,

Ik heb een script waarbij ik via jQuery een tabel aanmaak waarin ik heel snel een row kan opzoeken tussen 36.000+ andere rows.

Maar het duurt HEEEEL lang voordat het geladen is.

Weet iemand hoe ik dit kan verbeteren?


De query:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php

$sql
= "
SELECT
    ID,
    client_id,
    name,
    contact
FROM
    clients  
ORDER BY
    name, ID
"
;
?>


De tabel:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?php
CREATE TABLE IF NOT EXISTS `clients` (
  `ID` int(20) NOT NULL,
  `client_id` int(20) NOT NULL,
  `name` varchar(255) NOT NULL,
  `street` varchar(255) NOT NULL,
  `postal` varchar(255) NOT NULL,
  `city` varchar(255) NOT NULL,
  `country` varchar(255) NOT NULL,
  `phone` varchar(255) NOT NULL,
  `since` varchar(255) NOT NULL,
  `changed` varchar(255) NOT NULL,
  `contact` varchar(255) NOT NULL,
  `email` varchar(255) NOT NULL
) ENGINE=InnoDB AUTO_INCREMENT=36085 DEFAULT CHARSET=latin1;
?>


Alvast bedankt!
 
PHP hulp

PHP hulp

20/11/2019 11:16:38
 
Thomas van den Heuvel

Thomas van den Heuvel

09/06/2015 22:05:57
Quote Anchor link
Uhm, je ID is geen primary key / auto increment veld?

Verder zou je een index op name kunnen aanmaken zodat het sorteren sneller gaat.
 
Joni Fleischer
Moderator

Joni Fleischer

09/06/2015 22:07:31
Quote Anchor link
ID is primary AUTO_INCR

client_id en name zijn indexes
 
Thomas van den Heuvel

Thomas van den Heuvel

09/06/2015 22:45:59
Quote Anchor link
Heb je vastgesteld dat de laadtijd echt zit in het uitvoeren van de query, of toch ergens anders? Als je heel veel data naar je scherm stuurt, dan kan dat op zichzelf ook al veel tijd kosten.
 
Pipo Clown

Pipo Clown

09/06/2015 23:56:58
Quote Anchor link
Je huidige query selecteert niet één row van de 36.000 maar hij selecteert ze alle 36.000. Vandaar misschen de traagheid ?

Wanneer je één row wilt selecteren voeg dan een WHERE clausule toe.
 
Joni Fleischer
Moderator

Joni Fleischer

10/06/2015 18:04:25
Quote Anchor link
Hij moet juist die 36.000 rijen invoegen vanwege dat jQuery er een tabel van maakt waar je in kan zoeken.

Datatables.
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
<table id="table_archive" class="table table-striped table-bordered table-responsive" cellspacing="0" width="100%">
                                        <thead>
                                            <tr>
                                                <th>Client ID</th>
                                                <th>Bedrijfsnaam</th>
                                                <th>Contact persoon</th>
                                                <th>Actie</th>
                                            </tr>
                                        </thead>
                                
                                        <tbody>
                                            <?php
                                            $sql
= "
                                            SELECT
                                                ID,
                                                client_id,
                                                name,
                                                contact
                                            FROM
                                                clients  
                                            
                                            "
;
                                            
                                            if(!$res = mysqli_query($mysqli, $sql))
                                            {

                                                trigger_error('Fout in query: '.mysqli_error());
                                            }

                                            else
                                            {
                                                while($row = mysqli_fetch_assoc($res))
                                                {
                            
                                                    echo '<tr>';
                                                        
                                                        echo '<td>'.$row['client_id'].'</td>';
                                                        echo '<td>'.ucfirst(strtolower($row['name'])).'</td>';
                                                        echo '<td>'.ucfirst(strtolower($row['contact'])).'</td>';
                                                        
                                                        echo '<td class="center">';
                                                            echo '<a class="btn btn-info btn-xs" href="'.SITE_URL.'admin/gebruikers_wijzigen.php?id='.$row['ID'].'" title="Wijzigen">
                                                                <span class="glyphicon glyphicon-edit" style="margin-right:0;"></span>                                          
                                                            </a> '
;
                                                            
                                                        if(empty($disabled[$row['ID']]))
                                                        {

                                                            echo '<a onclick="show_confirm('.$row['ID'].')" class="btn btn-danger btn-xs" title="Blokkeren">
                                                                <span class="glyphicon glyphicon-remove" style="margin-right:0;"></span>                                          
                                                            </a>'
;
                                                        }

                                                        else
                                                        {
                                                            echo '<a onclick="de_show_confirm('.$disabled[$row['ID']].')" class="btn btn-success btn-xs" title="Deblokkeren">
                                                                <span class="glyphicon glyphicon-ok-sign" style="margin-right:0;"></span>                                          
                                                            </a>'
;
                                                        }

                                                            
                                                        echo '</td>';
                                                    echo '</tr>';
                                                }
                                            }

                                            ?>

                                        </tbody>
                                    </table>

- Aar -:
Gelieve in het vervolg bij code de [code][/code]-tags gebruiken.
Hier kan je meer lezen over de mogelijke opmaakcodes.
Alvast bedankt!
Gewijzigd op 12/06/2015 13:21:37 door - Ariën -
 
Eddy E

Eddy E

10/06/2015 19:02:21
Quote Anchor link
Dat is ook een hoop HTML.
Probeer, zeker bij zoveel rijen zo min mogelijk HTML te tonen. Des te sneller is je overdracht.
Alle onclick() kunnen er uit. Vang dat af met 1 regel jQuery.
De class= kan er ook uit. Doe dit via table tr td.center a
Haal de title="" weg. Die is leuk, maar wordt in je applicatie toch niet gebruikt (sorry, html-validators)
Verwijder de inline CSS op je <span>

Je gebruikt glyphicon: is die niet traag? Verwijder class="glyphicon ...." eens. Gaat het dan sneller?

Je PHP kan niet veel sneller/beter.
Je SQL wellicht wel door INDEXES, al gebruik je die bij een SELECT * niet echt.


Toevoeging op 10/06/2015 19:03:04:

En als je echt snel wil zoeken: kijk eens naar AJAX en laat de database in de database zoeken ;)
 
Thomas van den Heuvel

Thomas van den Heuvel

10/06/2015 19:51:53
Quote Anchor link
Ik heb ook altijd 36.000 resultaten tegelijkertijd nodig, jij ook?

Honestly, hang er een limiet in en/of maak een slimmere in- of opdeling.

Bijvoorbeeld: op bedrijf(snaam) of beginletter van achternaam. Of maak er een zoekpaneeltje bij dat je zelf kunt sorteren en filteren.

Met 36.000 records tegelijkertijd uitspugen creëer je niet meer, maar minder overzicht. Dat is terug naar het spreadsheet tijdperk.
 
Ward van der Put
Moderator

Ward van der Put

10/06/2015 19:56:24
Quote Anchor link
Eddy E op 10/06/2015 19:02:21:
Je PHP kan niet veel sneller/beter.
Je SQL wellicht wel door INDEXES, al gebruik je die bij een SELECT * niet echt.

Je zou om de 100 rijen een ob_flush() of flush() kunnen zetten, zodat de client alvast beeld heeft. Dan is de applicatie nog steeds even traag (strikt genomen zelfs wat trager), maar valt het minder op.

Verder zou je de SELECT-query kunnen uitbreiden met een ORDER BY voor de meest gebruikte sorteervolgorde. De meeste gebruikers sorteren een tabel zó dat ze de belangrijkste rijen bovenaan zien. En dáárop zet je vervolgens ook een INDEX met ASC of DESC.

Aangezien je INT(20) gebruikt in de tabeldefinitie en een PRIMARY KEY ontbreekt, vermoed ik zo dat we niet de hele tabel zien of de tabel inderdaad niet goed is ingedeeld.
 
Joni Fleischer
Moderator

Joni Fleischer

10/06/2015 19:59:04
Quote Anchor link
Ik heb het al!!!

Gewoon jSON uitpoepen :)

http://www.fleischer.nl/Grundfos/handlers/clients_processing.php

Nu gaat ie lekkah!

Bedankt !
 
- SanThe -

- SanThe -

10/06/2015 20:12:47
Quote Anchor link
Ja, gaat goed:

Quote:
Oeps...

Hier is even iets mis gegaan.
 
Johan K

Johan K

10/06/2015 23:06:47
Quote Anchor link
Joni Fleischer op 10/06/2015 19:59:04:
Ik heb het al!!!

Gewoon jSON uitpoepen :)

http://www.fleischer.nl/Grundfos/handlers/clients_processing.php

Nu gaat ie lekkah!

Bedankt !


Omdat niemand anders het vermeld, doe ik het maar even om het punt maar even duidelijk te maken.

NIEMAND heeft 36k rows nodig om wat te gaan doen. 1k resultaten is meer dan voldoende voor elk type website. En met 1k resultaten ben je zelfs gewoon slecht bezig.

Als jij denkt dat JSON jouw uitkomst is, prima en dan raad ik jouw aan om ergens hier te gaan eten.


Ik zeg er wel bij dat de database vrijwel altijd erg efficiënt is met het ophalen van data. Het verwerken daarvan zal jouw bottleneck wezen.
 
- wes  -

- wes -

11/06/2015 09:26:53
Quote Anchor link
Niemand commentaar op veldoptimalisatie? Telefoonnummers, postcodes hebben een redelijk standaard opmaak en lengte, een stuk korter dan 255 tekens. Hier kan je ook een boel winst op behalen.
 
Ward van der Put
Moderator

Ward van der Put

11/06/2015 09:50:56
Quote Anchor link
- wes - op 11/06/2015 09:26:53:
Telefoonnummers, postcodes hebben een redelijk standaard opmaak en lengte, een stuk korter dan 255 tekens. Hier kan je ook een boel winst op behalen.

Bij een VARCHAR helaas niet. Als je altijd postcodes van maximaal 7 karakters opslaat, maakt het voor de performance niet uit of je daarvoor nu een VARCHAR(7) of VARCHAR(255) gebruikt. Die extra ruimte wordt gewoon niet gebruikt als daarvoor geen data is.

Wat wel helpt: als postcodes altijd precies 7 karakters zijn, kun je beter een CHAR(7) gebruiken.

Verder kan bijvoorbeeld de `country` varchar(255) naar een aparte tabel. Dan heb je voor de sleutels alleen nog een TINYINT nodig.
 
Obelix Idefix

Obelix Idefix

11/06/2015 12:01:37
Quote Anchor link
since en changed klinkt als datum. In dat geval lijkt me varchar niet wenselijk.
 

12/06/2015 09:12:34
Quote Anchor link
Pro forma kan je nog de engine wijzigen naar MyISAM en een FIXED recordlengte gebruiken. In sommige gevallen is dat sneller dan InnoDB. Voor de rest ben ik het met iedereen eens, behalve natuurlijk dan dat door JSON als output van PHP te kiezen de SQL query sneller uitgevoerd zou worden. Ja, de laadtijd wordt verkort. Maar de laadtijd kan NOG korter door alle 36k rijen meteen in HTML uit te voeren. Dan heb je geen 2e HTTP request, EN wordt het ondersteund op browsers zonder JavaScript (handig voor SEO).
Wat is de use case voor de oplossing van Joni?
 
Ivo P

Ivo P

12/06/2015 09:30:31
Quote Anchor link
maar 36000 rows + overhead van de html-code om het als tabel te tonen (en alle andere opmaak erbij), is een flinke hoeveelheid data.

Dat moet overgestuurd worden en vervolgens moet de browser dat omzetten in iets dat getoond moet worden.

Met een beetje pech is je browser ook nog eens een paar duizend keer bezig om de breedte van elke kolom steeds opnieuw te bepalen.

Mogelijk dat daarna jQuery snel kan zoeken, maar je laadtijd is enorm.

Daarnaast: ook jQuery krijgt direct een dataset van 36000 records te verhapstukken. Dat moet ook ergens in het javascript geheugen komen.

Ik zou het meer zoeken in een soort auto-suggest oplossing waarbij je tijdens het typen in de database gaat zoeken met ajax
 
Elwin - Fratsloos

Elwin - Fratsloos

12/06/2015 13:13:14
Quote Anchor link
Joni Fleischer op 10/06/2015 18:04:25:
Hij moet juist die 36.000 rijen invoegen vanwege dat jQuery er een tabel van maakt waar je in kan zoeken.

Datatables.


Dus ik begrijp het goed als ik er vanuit ga dat je Datatables gebruikt? Dan zou ik gebruik maken van laden via Ajax, in combinatie met de optie pageLength.

Als het script dat de data ophaalt dan goed is haal je een maximaal aantal rijen op, die aan de filters voldoet van DataTables. Zie daarvoor Server side processing.
 
Joni Fleischer
Moderator

Joni Fleischer

29/09/2015 22:17:10
Quote Anchor link
Alles is al opgelost :)

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
<table id="table_archive" class="display table table-striped table-bordered table-responsive" cellspacing="0" width="98%" data-page-length='18'>
  <thead>
    <tr>
      <th width="10%">Client ID</th>
      <th>Bedrijfsnaam</th>
      <th width="20%">Contact persoon</th>
      <th width="30%">E-mailadres</th>
      <th width="5%">Actie</th>
    </tr>
  </thead>
</table>


Dan de jQuery code:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
var table = $('#table_archive').DataTable( {
    "language": {
        "sProcessing": "Bezig...",
        "sLengthMenu": "_MENU_ resultaten weergeven",
        "sZeroRecords": "Geen resultaten gevonden",
        "sInfo": "_START_ tot _END_ van _TOTAL_ resultaten",
        "sInfoEmpty": "Geen resultaten om weer te geven",
        "sInfoFiltered": " (gefilterd uit _MAX_ resultaten)",
        "sInfoPostFix": "",
        "sSearch": "Zoeken:",
        "sEmptyTable": "Geen resultaten aanwezig in de tabel",
        "sInfoThousands": ".",
        "sLoadingRecords": "Een moment geduld aub - bezig met laden...",
        "oPaginate": {
            "sFirst": "Eerste",
            "sLast": "Laatste",
            "sNext": "Volgende",
            "sPrevious": "Vorige"
        }
    },
    "processing": true,
    "serverSide": true,
    "ajax": "handle/clients_processing.php",
    "columnDefs": [ {
        "targets": -1,
        "data": null,
        "defaultContent": "<a class='btn btn-info btn-xs' href='#' title='Wijzigen'><span class='glyphicon glyphicon-edit' style='margin-right:0;'></span></a>"
    } ]
} );
$('#table_archive tbody').on( 'click', 'a', function () {
    var data = table.row( $(this).parents('tr') ).data();
    $(this).attr("href", "edit.php?id="+ data[ 4 ]);
});


Draait als een zonnetje!
Binnen 1 seconde 36.000+ rows uitgepoept.
Zal vast beter gecodeert kunnen worden, ben ik van overtuigd.
Gewijzigd op 29/09/2015 22:18:32 door Joni Fleischer
 
- Ariën -
Beheerder

- Ariën -

29/09/2015 23:00:15
Quote Anchor link
Joni Fleischer op 10/06/2015 19:59:04:
Ik heb het al!!!

Gewoon jSON uitpoepen :)

http://www.fleischer.nl/Grundfos/handlers/clients_processing.php

Nu gaat ie lekkah!

Bedankt !

Als je dit a-synchroon uitvoert, lijkt het sneller te gaan, maar dat is het niet in de praktijk. Misschien iets minder overhead door de parsing van HTML die je eerst had.

Gewoon de boel in partjes ophalen, of als iemand een bepaald record moet zoeken een auto-suggest gebruiken die met LIKE steeds verder zoekt.
Gewijzigd op 29/09/2015 23:01:52 door - Ariën -
 
Joni Fleischer
Moderator

Joni Fleischer

29/09/2015 23:06:32
Quote Anchor link
Aar!!!

Reageer ff op mijn andere forum bericht :P

Ik loop vast :'(
 

Pagina: 1 2 volgende »



Overzicht Reageren

 
 

Om de gebruiksvriendelijkheid van onze website en diensten te optimaliseren maken wij gebruik van cookies. Deze cookies gebruiken wij voor functionaliteiten, analytische gegevens en marketing doeleinden. U vindt meer informatie in onze privacy statement.