Can these queries be turned into a REPLACE INTO? - php

$sql2 = "SELECT `id` FROM `saa_game` WHERE `domain_id` = '".$row['id']."' AND `unique_id` = '".s($oGame->unique_id)."' AND `year` = '".$iYear."' AND `month` = '".$iMonth."' LIMIT 1";
$result2 = mysql_query($sql2) or die(mail('rpaiva#golevel.com','SAA Gather Error',mysql_error()));
if(mysql_num_rows($result2) == 1)
{
$row = mysql_fetch_assoc($result2);
$sql3 = "UPDATE `saa_game` SET `plays` = '".s($oGame->plays)."' WHERE `id` = '".$row['id']."' LIMIT 1";
$result3 = mysql_query($sql3) or die(mail('email#sample.com','SAA Gather Error',mysql_error()));
}
else
{
$sql3 = "INSERT INTO `saa_game` (`domain_id`,`type`,`source`,`unique_id`,`plays`,`year`,`month`) VALUES ('".$row['id']."','".s($oGame->type)."','".s($oGame->source)."','".s($oGame->unique_id)."','".s($oGame->plays)."','".$iYear."','".$iMonth."')";
$result3 = mysql_query($sql3) or die(mail('email#sample.com','SAA Gather Error',mysql_error()));
}
I've got this set of queries running 40,000 times on a single page load on a cron job every 10 minutes. This takes so long that it almost runs into the next cron job. If I could reduce this into one query instead of two, that'd be great. (as long as there will actually be a performance difference)

If the select hits all of the right indexes, there won't be a performance increase. In fact, it's likely to be worse! MySQL's REPLACE INTO is implemented as a delete, then an insert!
Consider MySQL's INSERT INTO ... ON DUPLICATE KEY UPDATE instead.
Keep in mind that both of these options are exclusive to MySQL.

Related

Find a next record after disabling a record?

I have a created a function changeIp() to disabled a record and return a new record. As you can see I am using 3 SQL query.
Is there a better way doing to reduce number of SQL queries?
function changeIp() {
// Find 1 record which is not disabled
$SQL = "SELECT * FROM ip WHERE disable = 0 order by id limit 1";
$qIp = mysql_query($SQL) or die(mysql_error());
$qrow = mysql_fetch_assoc($qIp);
// Disable a record
$id = $qrow['id'];
$SQL = "UPDATE ip set disable = 1 WHERE id = $id";
mysql_query($SQL) or die(mysql_error());
// Return the next record
$SQL = "SELECT * FROM ip WHERE disable = 0 order by id limit 1";
$qIp = mysql_query($SQL) or die(mysql_error());
$qrow = mysql_fetch_assoc($qIp);
return $qrow['ip'];
}
You should use "mysqli" or php, but that is a separate matter from your question.
Your queries are fine. You can't really do an update and select in a single statement. You can improve performance with an index on ip(id, disable). And, an index on ip(disable, id) might also be beneficial, depending on a number of factors.

How to do two DB queries at once in PHP?

I have two queries but can I have them as just one
$sql = ("SELECT * FROM table WHERE title='$title' LIMIT 1");
$sql = ("UPDATE table SET views = views+1 where title='$title' ");
$query = mysql_query($sql) or die("Error Connecting To db");
At the moment the 2nd one works but not the first one.
This is your code:
$sql = ("SELECT * FROM table WHERE title='$title' LIMIT 1");
$sql = ("UPDATE table SET views = views+1 where title='$title' ");
$query = mysql_query($sql) or die("Error Connecting To db");
First, the first $sql will not run because you are overwriting the contents of that first $sql with new content in the next line.
Then just looking at your logic, here is your first query:
SELECT * FROM table WHERE title='$title' LIMIT 1
I assume that is to get the entry with the title equalling $title and nothing else, right? But then your next query is this:
UPDATE table SET views = views+1 where title='$title'
You are updating the value where title='$title' anyway. So the first query is not even needed. So problem solved, right? Well you might want to add the LIMIT 1 to the second query like this:
UPDATE table SET views = views+1 where title='$title' LIMIT 1
But honestly the logic of updating a DB based on whether an item title matches seems messy. What if two items have the same title? Yes, you are limiting things by 1 but by what criteria? If you have three items with the same title, which gets updated?
You need more differentiation for your app structure. But I think that is fair for what is essentially a newbie question.
Run the two queries separately
$sql1 = ("SELECT * FROM table WHERE title='$title' LIMIT 1");
$qry = mysql_query($sql1);
if (mysql_num_rows($qry) > 0)
{
while ($res = mysql_fetch_object($qry))
{
// -- contents --
}
$sql = ("UPDATE table SET views = views+1 where title='$title' ");
$query = mysql_query($sql) or die("Error Connecting To db");
}

MySQL - Batch rename all rows in PHP

So in this piece of code, I just deleted a row from the table, and so, the values for img_pos were:
1,2,3,4,5
And now, they are (assuming we deleted the third entry):
1,2,4,5
Of course, I want this to be:
1,2,3,4
So I have to batch rename the rows.
I got this, but doesn't seem to work....
$sql = "SELECT * FROM $tableImg WHERE img_acc = $accid ORDER BY img_pos";
$res = mysql_query($sql);
$num = mysql_num_rows($res);
$i = 0;
$n = 1;
while($i<$num){
$sql = "SELECT * FROM $tableImg WHERE img_acc = $accid ORDER BY img_pos DESC LIMIT $i,1";
$res = mysql_query($sql);
$row = mysql_fetch_array($res);
$img_pos = $row['img_pos'];
$sql = "UPDATE $tableImg SET img_pos = '$n' WHERE img_acc = '$accid' AND img_pos = '$img_pos'";
$res = mysql_query($sql);
$i++;
$n++;
}
mysql_close();
$tableImg is just a variable containing the table name, that works just fine.
I guessthe problem is somewhere around "$img_pos = $row['img_pos'];", because all the querys are used somewhere differently, be it slightly different, and they should work...
Thanks in advance!
I ended up simply doing this:
$i = 1;
while($row = mysql_fetch_array($res)){
$old_pos = $row['img_pos'];
$sql = "UPDATE $tableImg SET img_pos = $i WHERE img_acc = $accid AND img_pos = $old_pos";
$res = mysql_query($sql);
$i++;
};
This is quite possible, just totally unnecessary. The nice thing about digital data is that you don't have to look at it so it doesn't matter if it's a bit gappy, does it?
If you REALLY want to do this (say, you are building an application and you are just cleaning up the stuff you deleted whilst working on it) the following example will do in in SQL, as this simple example shows:
CREATE TABLE disorder (id int,stuff CHAR(6));
CREATE TABLE disorder2 (id SERIAL,stuff CHAR(6));
INSERT INTO disorder (id,stuff)
VALUES
('1','ONE'),
('2','TWO'),
('3','THREE'),
('4','FOUR'),
('5','FIVE');
DELETE FROM disorder WHERE id='3';
INSERT INTO disorder2 (stuff) SELECT stuff FROM disorder;
TRUNCATE TABLE disorder;
INSERT INTO disorder SELECT * from disorder2;
DROP TABLE disorder2;
This can be seen in action on sqlfiddle but it's pretty obvious. If you do a SELECT * from disorder, you will see why you probably shouldn't do this sort of thing.
Your tables really do need to have primary keys. This speeds searches/indexing and makes them useful. Look up database normal forms for a thorough discussion of the reasoning.

SELECT then immediately DELETE mysql record

I have a PHP script that runs a SELECT query then immediately deletes the record. There are multiple machines that are pinging the same php file and fetching data from the same table. Each remote machine is running on a cron job.
My problem is that sometimes it is unable to delete fast enough since some of the machines ping at the exact same time.
My question is, how can I SELECT a record from a database and have it deleted before the next machine grabs it. For right now I just added a short delay but it's not working very well. I tried using a transaction, but I don't think it applies here.
Here is an example snippet of my script:
<?php
$query = "SELECT * FROM `queue` LIMIT 1";
$result = mysql_query($query) or die(mysql_error());
while($row = mysql_fetch_array($result)){
$email = $row['email'];
$campaign_id = $row['campaign'];
}
$queryx = "DELETE FROM `queue` WHERE `email` = '".$email."'";
$resultx = mysql_query($queryx) or die(mysql_error());
?>
Really appreciate the help.
If you're using MariaDB 10:
DELETE FROM `queue` LIMIT 1 RETURNING *
Documentation.
well I would use table locks
read more here
Locking is safe and applies to one client session.
A table lock protects only against inappropriate reads or writes by other sessions.
You should use subquery as follows...
<?php
$queryx = "DELETE FROM `queue` WHERE `email` IN (SELECT email FROM `queue` LIMIT 1)";
$resultx = mysql_query($queryx) or die(mysql_error());
?>
*Note: Always select only the fields you want... try to avoid select *... this will slow down the performance
run an update query that will change the key before you do your select. Do the select by this new key, whicj is known only in the same session.
If the table is innoDB the record is locked, and when it will be released, the other selects won't find the record.
Put your delete queries inside the while loop, just incase you ever want to increase the limit from your select.
<?php
$query = mysql_query("SELECT * FROM `queue` LIMIT 1") or die(mysql_error());
while($row = mysql_fetch_array($query)){
mysql_query("DELETE FROM `queue` WHERE `email` = '" . $row['email'] . "' LIMIT 1") or die(mysql_error());
}
?>
The above code would be just the same as running:
mysql_query("DELETE FROM `queue` LIMIT 1") or die(mysql_error());
Be careful using your delete query, if the email field is blank, it will delete all rows that have a blank email. Add LIMIT 1 to your delete query to avoid multiple rows being deleted.
To add a random delay, you could add a sleep to the top of the script,
eg:
<?php
$seconds = mt_rand(1,10);
sleep($seconds);
?>

Question if my code is a low resources one

Hi please tell me if this is a low resources piece of code, and if it is not how shall I change it ? Thank you!
$query = 'SELECT MAX(ID) as maxidpost
FROM wp_posts';
$result = mysql_query($query) or die(mysql_error());
while($row = mysql_fetch_array($result)) {
$postid = $row['maxidpost']+1;
echo "p=$postid";
The improvement is debatable, but:
$query = 'SELECT MAX(ID) +1 as maxidpost
FROM wp_posts';
$result = mysql_query($query) or die(mysql_error());
while($row = mysql_fetch_array($result)) {
echo "p = ". $row["maxidpost"];
You can do math in SQL statements, saving you from having to do the operation in PHP.
It'd be nice to know what you're using this for - if it's the next id to be inserted, using AUTO_INCREMENT would be safer. SELECT statements are generally given higher priority over INSERT/UPDATE/DELETE, and thus can read before an insert from another source -- which would risk duplicates.
Because you are returning one row, you should do something like:
$query = 'SELECT MAX(ID) as maxidpost FROM wp_posts';
$result = mysql_query($query) or die(mysql_error());
$row = mysql_fetch_row($result);
$postid = $row['maxidpost']+1;
echo "p=$postid";
Otherwise seems about as good as you could do.
You can recalculate the post code after each post. Start with zero. Select it from the database, use that id, add one, save back to database.
Or you could use auto increment (if that is possible).

Categories