I have a request to get data in my mySQL database (36,848 entries).
Then I format and append them with jQuery on my web page.
These two operations take 2 minutes and 30 seconds.
During this time, no other operation is possible on the page.
Is there a way to optimize this to speed up the process?
Like this, it's unusable.
My PHP function
<?php
function get_my_customers() {
$req = $bdd->prepare("SELECT * FROM clients ORDER BY raison_sociale");
$req->execute();
$customers = $req->fetchAll(PDO::FETCH_ASSOC);
return $customers;
}
if(isset($_POST['ajax'])){
$result = get_my_customers();
echo json_encode($result);
}
?>
Data retrieval in jQuery (Ajax)
function get_my_customers(){
var customers;
$.ajax({
url: "model/application/*******/customers/get_my_customers.php",
async: false,
type: "POST",
dataType: 'json',
data: {ajax: 'true'},
success: function(data)
{
customers = data;
}
});
return customers;
}
var my_customers = get_my_customers();
$('#customers_list').append('<div class="list_card" card="customers_list"></div>');
$.each(my_customers, function(key, val){
if(val.enseigne == null){
var enseigne = '';
}else{
var enseigne = ',' + val.enseigne;
}
$('.list_card[card="customers_list"]').append(''+
'<div class="list_card_element">'+
'<div><b>'+ val.numero_client +'</b></div>'+
'<div>'+
'<b>'+ val.raison_sociale +'</b>' + enseigne +
'<br>'+
val.cp_livraison + ', ' + val.adresse_livraison +
'</div>'+
'</div>'
);
});
Do you know what I can do to speed up processing time?
I've tried limiting the SELECT query to only the fields I need but that doesn't improve processing time.
I wonder if it's not rather the jQuery layout that takes time rather than the SQL query.
Thank you !
Use devtools in your browser to determine which step is causing the slowdown. The Network tab will show you the Ajax request and the time interval of the data fetch. If that time interval is not the issue, it's likely with the Javascript. You can get deeper on the Javascript performance using the Performance tab.
try to use indexes see that
MySQL can use an index on the columns in the ORDER BY (under certain conditions). However, MySQL cannot use an index for mixed ASC,DESC order by (SELECT * FROM foo ORDER BY bar ASC, pants DESC). Sharing your query and CREATE TABLE statement would help us answer your question more specifically.
I just passed from 2 minutes and 30 secondes to 14 secondes with this optimization.
var construct_customers = "";
$.each(my_customers, function(key, val){
if(val.enseigne == null){
var enseigne = '';
}else{
var enseigne = ',' + val.enseigne;
}
construct_customers += '<div class="list_card_element">'+'<div><b>'+ val.numero_client +'</b></div>'+'<div>'+'<b>'+ val.raison_sociale +'</b>' + enseigne +'<br>'+val.cp_livraison + ', ' + val.adresse_livraison +'</div>'+'</div>';
//OLD CODE
// $('.list_card[card="customers_list"]').append(''+
// '<div class="list_card_element">'+
// '<div><b>'+ val.numero_client +'</b></div>'+
// '<div>'+
// '<b>'+ val.raison_sociale +'</b>' + enseigne +
// '<br>'+
// val.cp_livraison + ', ' + val.adresse_livraison +
// '</div>'+
// '</div>'
// );
});
$('.list_card[card="customers_list"]').append(construct_customers);
I'm impressed
Related
I am building a facility on a website (using Symfony2) that allows the user to create reports and display them on a screen using AJAX. The reports are effectively SQL statements that are created on the fly and are then ran on the Database.
The problem I have is that I can't fathom a way to display these results to the screen without first knowing what fields are used in the report. The queries could contain just 2 fields from a table, or 15 fields, and I'd like the code to be robust enough to handle this.
So far, this is the code I'm using:
$.ajax({
type: 'POST',
url: urlLink,
success: function (data) {
var Type = (data.recordType);
var Results = (data.results);
var Name = (data.name);
var Description = (data.description);
var Titles = (data.titles);
$('#reportName').text(Name);
$('#reportDescription').text(Description);
$('#listTable > tbody:last').empty();
$('#listTable > thead:last').empty();
$('#listTable > thead:last').append('<tr>'+Titles+'</tr>');
$.each(Results, function(i, item) {
$('#listTable > tbody:last').append('<tr><td>' + Results[i] + '</td><td>' + Results[i] + '</td><td>' + Results[i] + '</td><td>' + Results[i] + '</td><td>' + Results[i] + '</td><td>' + Results[i] + '</td></tr>');
});
}
});
The variable Titles comes from the query, as when the user is adding fields to the database these are then added to a string which I then explode using PHP in the controller.
Inside the foreach, every column comes back with [object Object]. When I remove the [i] from the code and replace it with .column-name it will then work. But this is what I'm trying to avoid. I'd like to have something similar to what I do with the Table Titles.
Maybe try this, and show output of console.log(data);
console.log(data);
var data = $.parseJSON(data);
$.each(data, function() {
$.each(this, function(k, v) {
/// do stuff
});
});
My question has part solutions on this site but not a complete answer.
On my wordpress homepage I display a counter of the number of questions answered within our webapp. This is displayed using jQuery and AJAX to retrieve the question count from a php file and works fine with this code.
jQuery(document).ready(function() {
function load() {
jQuery.get('/question_count.php', function(data) {jQuery('#p1').html( data ); });
}
load();
setInterval(load,10000);
});
Is there a way to display counting up to the new number retrieved rather than just immediately displaying it?
Something like this?
function countTo(n) {
var p = $("#p1"),
c = parseInt(p.html(), 10) || 0,
dir = (c > n ? -1 : 1); // count up or down?
if (c != n) {
p.html((c + dir) + "");
setTimeout(function() {
countTo(n);
}, 500);
}
}
Call it in your success handler
jQuery.get('/question_count.php', function(data) {
var n = parseInt(data, 10);
countTo(n);
});
Example
You will need to do a setInterval event so that the count up is visable to human eyes.
This may be a problem if you eventually reach enough questions where the count takes a long time to reach the end.
Code will look like this:
function load(){
jQuery.get('/question_count.php', function(data){
var curr = 0;
var max = parseInt(data);
var interval = setInterval(function(){
if(curr==max){
clearInterval(interval);
}
jQuery('#p1').html( curr );
curr+=1; //<-- if the number of questions gets very large, increase this number
},
10 //<-- modify this to change how fast it updates
});
}
}
How do we implement a timer to send an ajax request to refresh data (like new entries from other users on database) every one minute. I am using $.ajax from jquery.
My intention is to send the time where there was the last update so the server does not send repeated data. Only rows created from after that time.
My server script is php.
For Sending Date and Time You can use this function
var date = new Date();
var date = date.getUTCFullYear() + '-' +
('00' + (date.getUTCMonth()+1)).slice(-2) + '-' +
('00' + (date.getUTCDate()).slice(-2) + ' ' +
('00' + date.getUTCHours()).slice(-2) + ':' +
('00' + date.getUTCMinutes()).slice(-2) + ':' +
('00' + date.getUTCSeconds()).slice(-2);
Above will format the date and time in mysql format which you pass through variable to mysql query and then use setInterval to pass current time after every minute
setInterval(function(){
$.ajax({
type:"POST",
data:"Time="+ date,
url:"serverRef",
success: function(data){
// On success
}
});
},60000);
Note: You can also use same technique in Server side as well
setInterval with jQuery's post would work wonders. Make sure if you have a lot of visitors, remember to cache, otherwise you can rack up a lot of queries without noticing, which in the past I've noticed can overwhelm some hosts and essentially take you offline.
var ajax = window.setInterval(function(){
$.post('path/to/my/script.php', function(data){
if(data == "stop")
{
clearInterval(ajax);
return;
}
$('#statistics').html(data);
});
}, 60000);
I have a table which I can dynamically add and delete any number of rows to. Once the data is all entered by the user I am using the jQuery AJAX functionality to POST it to a mysql database so there is no page redirect or refresh.
The only way I could think of getting it to work was using this for loop in my jQuery, effectively posting each row to the database separately. How dumb is this? Should I be getting all the table data and posting it once? There could be any number of rows varying on user and the user could add and delete rows as much as he wants before submitting.
The strange i variable counting is due to there being two th rows at the top of the table. I couldn't work out a smart way of doing this.
I was a bit paranoid about the data always being associated with the correct row.
Thankyou for your time.
jQuery(function() {
jQuery(".button1").click(function() {
// process form here
var rowCount = jQuery('#dataTable tr').length;
for (var i = 2; i < rowCount; i++){
// the four elements of each row I am storing to the mysql
var txtRow1 = jQuery('#txtRow' + (i-1)).val();
var tickerRow1 = jQuery('#tickerRow' + (i-1)).val();
var quantRow1 = jQuery('#quantRow' + (i-1)).val();
var valueRow1 = jQuery('#valueRow' + (i-1)).val();
var dataString = 'txtRow1='+ txtRow1 + '&tickerRow1=' + tickerRow1 + '&quantRow1=' + quantRow1 + '&valueRow1=' + valueRow1;
//alert (dataString);return false;
jQuery.ajax({
type: "POST",
url: "http://rccl.co.uk/form_action1.php",
data: dataString
});
};
return false;
});
});
It looks very clearly to me as if you have a well-established index of the row in question, using your variable i. Most form handlers server-side will unpack repeated keys of the form into a list, for stuff like many checkboxes with the same name. You could exploit that here.
datastring = '';
for(var i=2; i<rowCount; i++) {
var txtRow1 = jQuery('#txtRow' + (i-1)).val();
var tickerRow1 = jQuery('#tickerRow' + (i-1)).val();
var quantRow1 = jQuery('#quantRow' + (i-1)).val();
var valueRow1 = jQuery('#valueRow' + (i-1)).val();
dataString = datastring + 'index[]=' + (i-1) + 'txtRow1[]='+ txtRow1 + '&tickerRow1[]=' + tickerRow1 + '&quantRow1[]=' + quantRow1 + '&valueRow1[]=' + valueRow1;
}
Then make the ajax call with the whole string.
On the server-side, you should get arrays for each of these, the first of each of which corresponds to the first row, the second of each of which corresponds to the second row, and so on.
It's been a long time since I used PHP, but I believe the [] symbols for each key item are necessary to clue PHP's $_POST that it should convert the various keys' contents into arrays.
I would try posting it all at once.
Reasons
fewer calls, less chance of your message getting lost in transit (your server rejecting requests because of flood)
you don't have to worry about requests responding out of order (maybe not an issue, but having an ass load of jumbled responses could potentially be an issue)
it will be faster for large numbers of rows getting saved at once
I'm having trouble understanding why my code will not work asynchronously.
When running asynchronously the get_price.php always receives the same $_GET value even though the alert before outputs a unique $_GET value.
var arraySize = "<? echo count($_SESSION['items']); ?>"; //get items count
var pos = 0;
var pid;
var qty;
getPriceAjax();
function getPriceAjax()
{
pid = document.cartItemForm.elements[pos].id; //product id
qty = document.cartItemForm.elements[pos].value; //quantity
alert('Product: ' + pid + ' Quantity: ' + qty);
$.ajax({
url:"includes/ajax_php/get_price.php",
type:"GET",
data:'pid='+pid+'&qty='+qty,
async:true,
cache:false,
success:function(data){
while(pos < arraySize)
{
document.getElementById(pid + 'result').innerHTML=data;
pos++;
getPriceAjax();
}
}
})
}
I dealt with a similar problem. I can't quite remember what was going on, so this answer may not be too helpful. Your server may be caching the response. Try using POST.
Try adding a bit of random number to your get URL so the server doesn't cache it, like so:
url:"includes/ajax_php/get_price.php&rnd=" + Math.floor(Math.random()*10000)
It could also be a timing issue. Since it is asynchronous, it could be stepping through the loop and alerting before the value comes back. Your pos counter won't get incremented until it returns, so you will always be getting the price of pos = 0 until your call comes back. I would move the incrementer outside the success function. Also, try moving the alert inside of the success function.
function getPriceAjax()
{
pid = document.cartItemForm.elements[pos].id; //product id
qty = document.cartItemForm.elements[pos].value; //quantity
$.ajax({
url:"includes/ajax_php/get_price.php",
type:"GET",
data:'pid='+pid+'&qty='+qty,
async:true,
cache:false,
success:function(data){
while(pos < arraySize)
{
alert('Product: ' + pid + ' Quantity: ' + qty);
document.getElementById(pid + 'result').innerHTML=data;
getPriceAjax();
}
}
});
pos++;
}
Recursion almost beat me...
Instead of using a while loop it should have been an if conditional statement.
while(pos < ArraySize) WRONG! - executes the first set of parameters arraySize times.
if(pos < ArraySize) CORRECT! - executes the first, then second, and so on...