Increase speed of PHP and MySQL webservice - php

I have created a web service using php and mysql to insert and return data for my app. One of the main complaints from users is the response is too slow, which I agree, as it takes anywhere from 5-10 seconds to complete task. Originally thought it was a hosting performance issue, but has not made a difference (godaddy versus AWS).
Looking at the SQL code in my php files, I think that is the issue. I'm looking to re-write to increase speed. I believe the issue is I use timestamps, and to return I always look for the max(timestamp).
Here is my input SQL statement:
$insert = mysql_query("INSERT INTO meals (user, date, meal, timeStamp, food) VALUES ('$user','$date','$meal','$timeStamp','$food')");
Here is my return SQL statement:
$query = mysql_query ("SELECT * FROM meals WHERE user = '$user' AND date = '$date' AND meal = '$meal' AND timeStamp = (SELECT MAX(`timeStamp`)FROM meals WHERE user = '$user' AND date = '$date' AND meal = '$meal')");
Would I be better off using an UPDATE or similar instead of using timestamps? Any other recommendations?

This is your query:
SELECT *
FROM meals
WHERE user = '$user' AND date = '$date' AND meal = '$meal' AND
timeStamp = (SELECT MAX(`timeStamp`)
FROM meals
WHERE user = '$user' AND date = '$date' AND meal = '$meal'
);
Assuming that you want only one row, the first simplification is:
SELECT *
FROM meals
WHERE user = '$user' AND date = '$date' AND meal = '$meal'
ORDER BY timestamp desc
LIMIT 1;
Next, indexes will help this query. In fact, an index on meals(user, date, meal, timestamp) would work for both the where and the order by. That should improve performance.

Related

how to return records with dates in array less than a particular date

To simplify, each record in a database has Company Name, the Total Spend and Nights reserved. The Nights reserved are stored in the form of a string and then parsed later in the process.
example: Customer= "Bob's Heating" Total= 3000 Reserved= "1/2/2017,1/3/2017,1/5/2017..."
I need to write a query that selects all record whose reservations begin on or before a particular date, so if the target date was "1/4/2017" Bob Heating's record above would be returned.
Any help would be appreciated,
Jim
1.) Create a new table in your database called "reservation_dates" that has the columns: row_id (INT), the_date (DATE)
2.) Run a script in PHP that moves all of those dates into another table that stores them as DATE data types.
Example PHP script:
$statement = "SELECT * FROM my_table";
$result = mysqli_query($con, $statement) or die(mysqli_error($con));
while ($row = mysqli_fetch_assoc($result))
{
$dates = explode(",", $row['Reserved']);
foreach($dates as $date)
{
mysqli_query($con, "INSERT INTO reservation_dates (row_id, the_date) VALUES ('".$row['id']."', '$date')") or die(mysqli_error($con));
}
}
Run the PHP script. Now you will have all of your dates in a relational table called reservation_dates.
Next, to select all of the rows that fall within 1/4/2017, run a query such as
SELECT customer.* FROM reservation_dates reservation JOIN my_table customer ON customer.id = reservation.row_id WHERE MAX(reservation.the_date) >= '2017-04-01' AND MIN(reservation.the_date) <= '2017-04-01' GROUP BY row_id
I typed this quickly without actually trying the code but that's the general approach I would take. Hope it helps!
select *
from dbo.March2010 A
where A.Date <= Convert(datetime, '2010-04-01' )

Find out how often a value is between 2 dates in mysql

Hi with the follow code I request what dates are all in my database without duplicates.
Then I save it to an array. In the array I also need an other value.
The value I need is how much users are in one day in the database without duplicates.
For Example the array must later lookslike 23.07.2013 - 10, 24.07.2013 - 50 (users).
I search for several hours but I don't find a good mysql query.
$query = "SELECT id, user, timestamp FROM stat WHERE timestamp BETWEEN '$datum1' AND '$datum2' GROUP BY timestamp";
$result = mysql_query($query,$db);
while($row = mysql_fetch_assoc($result))
{
mysql_num_rows($result);
$dataset1[] = array(strtotime($row['timestamp']),$number_of_users_on_this_day);
}
Try:
$query = "SELECT id, user, COUNT(*) as count FROM stat WHERE timestamp BETWEEN '$datum1' AND '$datum2' GROUP BY timestamp";
This will return the number of entries in the value 'count'
if you want distinct data, in place of * use
COUNT(DISTINCT id)
with whatever field you want to be unique in place of 'id'

How do I count unique visits base on date

I have a reports table where i count hits by just using the code below.
// Get hits
$hits_query = mysql_query("SELECT COUNT(*) AS `count` FROM `reports` WHERE `stuff_id` = ".$row->id."");
$fetch_hits = mysql_fetch_array($hits_query);
$hits = $fetch_hits['count'];
That code works great and does exactly what i want but what i want now is how to get unique hits?
In my reports table i store every access so theres multiple log for each user base on the stuff_id . In my reports table I store the date as 01-23-2013 on each report, along with the user ip and stuffed which every 24 hours change from 2 to 1.
You need a field that uniquely identifies the user. I am going to assume for my example that it is user_ip. Change this:
$hits_query = mysql_query("SELECT COUNT(*) AS `count` FROM `reports` WHERE `stuff_id` = ".$row->id."");
To this:
$hits_query = mysql_query("SELECT COUNT(DISTINCT `user_ip`) AS `count` FROM `reports` WHERE `stuff_id` = ".$row->id."");
NOTE: mysql library will be deprecated as of PHP 5.5 and removed in future versions of PHP. It would be a good idea to start planning a migration away from it.
you can do this:
$hits_query = mysql_query("SELECT COUNT(DISTINCT `user_ip`) AS `count` FROM `reports` WHERE `stuff_id` = ".$row->id."");
Or if you want a unique response, you can do this:
$user-IP = "Put here the ip adress of the user that you want";
$hits_query = mysql_query("SELECT COUNT(*) AS `count` FROM `reports` WHERE `user_ip` = ".$user-IP."");

Adding auction bids to MySQL table

I am currently working on a simple auction site. I am storing bids in their own MySQL table called 'bids'. I am wondering what is the best way of ensuring that two of the same bids are not submitted at the exact same time.
My current strategy for verifying that the bid submitted is in fact the highest bid is to do the following (as an example):
$sql = "SELECT * FROM bids WHERE amount >= '".$bidamount."'";
$result = mysql_query($sql);
if(mysql_num_rows($result) == 0) {
$sql = "INSERT INTO bids SET amount = '".$bidamount."'";
mysql_query($sql);
$bidid = mysql_insert_id();
}
The problem with the above set of queries is that between the time the SELECT query is run and the INSERT query is run, another user could insert the same bid.
Is there some way to lock the table during the SELECT that would prevent this double-bidding from occurring? My main concern with locking tables for such a purpose would be performance problems when you have a lot of people bidding at once.
You may want to make conditional insert, like:
$amount = intval($amount);
$query = "
INSERT INTO
bids(amount)
SELECT
{$amount}
FROM
(SELECT 1) tmp_tbl
WHERE NOT EXISTS(
SELECT * FROM bids WHERE amount >= {$amount}
)
";
and check for affected (inserted) rows.

A logical problem with two tables

Hey guys, I created a list for fixtures.
$result = mysql_query("SELECT date FROM ".TBL_FIXTURES." WHERE compname = '$comp_name' GROUP BY date");
$i = 1;
$d = "Start";
while ($row = mysql_fetch_assoc($result))
{
$odate = $row['date'];
$date=date("F j Y", $row['date']);
echo "<p>Fixture $i - $d to $date</p>";
}
As you can see from the query, the date is displayed from the fixtures table.
The way my system works is that when a fixture is "played", it is removed from this table. Therefore when the entire round of fixtures are complete, there wont be any dates for that round in this table. They will be in another table.
Is there anyway I can run an other query for dates at the same time, and display only dates from the fixtures table if there isnt a date in the results table?
"SELECT * FROM ".TBL_CONF_RESULTS."
WHERE compid = '$_GET[id]' && type2 = '2' ORDER BY date"
That would be the second query!
EDIT FROM HERE ONWARDS...
Is there anyway I can select the date from two tables and then only use one if there are matches. Then use the rows of dates (GROUPED BY) to populate my query? Is that possible?
It sounds like you want to UNION the two result sets, akin to the following:
SELECT f.date FROM tbl_fixtures f
WHERE f.compname = '$comp_name'
UNION SELECT r.date FROM tbl_conf_results r
WHERE r.compid = '$_GET[id]' AND r.type2 = '2'
GROUP BY date
This should select f.date and add rows from r.date that aren't already in the result set (at least this is the behaviour with T-SQL). Apparently it may not scale well, but there are many blogs on that (search: UNION T-SQL).
From the notes on this page:
//performs the query
$result = mysql_query(...);
$num_rows = mysql_num_rows($result);
//if query result is empty, returns NULL, otherwise,
//returns an array containing the selected fields and their values
if($num_rows == NULL)
{
// Do the other query
}
else
{
// Do your stuff as now
}
WHERE compid = '$_GET[id]' presents an oportunity for SQL Injection.
Are TBL_FIXTURES and TBL_CONF_RESULTS supposed to read $TBL_FIXTURES and $TBL_CONF_RESULTS?
ChrisF has the solution!
One other thing you might think about is whether it is necessary to do a delete and move to another table. A common way to solve this type of challenge is to include a status field for each record, then rather than just querying for "all" you query for all where status = "x". For example, 1 might be "staging", 2 might be "in use", 3 might be "used" or "archived" In your example, rather than deleting the field and "moving" the record to another table (which would also have to happen in the foreach loop, one would assume) you could simply update the status field to the next status.
So, you'd eliminate the need for an additional table, remove one additional database hit per record, and theoretically improve the performance of your application.
Seems like what you want is a UNION query.
$q1 = "SELECT DISTINCT date FROM ".TBL_FIXTURES." WHERE compname = '$comp_name'";
$q2 = "SELECT DISTINCT date FROM ".TBL_CONF_RESULTS.
"WHERE compid = '$_GET[id]' && type2 = '2'";
$q = "($q1) UNION DISTINCT ($q2) ORDER BY date";

Categories