UPDATE tbl SET field = x WHERE field != x? - mysql

Are there any performance gain with this query:
UPDATE tbl SET field = 1 WHERE field != 1
over this
UPDATE tbl SET field = 1
Does the SQL parser already know that he doenst' need to update row that already are field = 1 ?

The condition field != 1 will likely make it faster especially in the case where most values are already 1. Assuming an index is available for optimizing, the database engine will be able to avoid examining most of the records in that case.
More importantly, perhaps, is that the queries may not have the same result. If any of the field values are NULL, the first UPDATE statement will not update those values. The second query would set the NULLs to 1.
Another (fairly obvious) case where they would not be equivalent is that UPDATE triggers would fire for all records for the second query (without the condition) but they would not fire for the first query for the skipped rows.

If there are just a few fields which are != 1, then there are most definitely performance gains in adding the WHERE clause. Even if MySQL did not write the value to disk, it still would need to look at every row to see if it needs to write it or not, but it certainly does not add the WHERE clause by itself.

Related

Mysql update caused entire table to be updated with same value

I need assistance trying to find a problem where 1 record/row was updated but the entire table got updated with the same value. Need to understand how this could have happened and implement a method to prevent it from doing so again.
update TABLE set pushID='1234567890' where userID='111222333' ;
What would that update statement do if the userID value equaled nothing or equaled NULL? Could that cause the update statement to update every single row with the same pushID?
IE: update TABLE set pushID='1234567890' where userID='' ;
Could a blank userID value cause this? If not, what could cause this? If so, how could I write the query statement to prevent this from happening again?
What would that update statement do if the userID value equaled nothing or equaled NULL?
If the userID is NULL, then the condition becomes userID = NULL. This will always evaluate as false. In other words, no record will be updated.
If the userID is the empty string, then the condition becomes userID = ''. This will only update records where userID is equal to the empty string. I would expect that userID is the primary key of your table, so it would be suprising the find an empty value. And even if there is one, it will be unique, so a unique record will be updated.
As you see, none of the two above use case would generate a massive update of the table. The most probable option is that the query was triggered without an actual WHERE clause, like:
update TABLE set pushID='1234567890'
In case these are altogether integer ID, you should not convert them to string with ''. Doing so may lead to unexpected results (never tried, but it seems to be a possible cause for the comparison in the WHERE condition to fail). For example:
UPDATE TABLE SET pushID=1234567890 WHERE userID=111222333;
When all records are being updated, the query lacks the WHERE condition. Make sure to have posted the correct query, because this query should update nothing when the WHERE condition fails to match.

Mysql Update one column of multiple rows in one query

I've looked over all of the related questions i've find, but couldn't get one which will answer mine.
i got a table like this:
id | name | age | active | ...... | ... |
where "id" is the primary key, and the ... meaning there are something like 30 columns.
the "active" column is of tinyint type.
My task:
Update ids 1,4,12,55,111 (those are just an example, it can be 1000 different id in total) with active = 1 in a single query.
I did:
UPDATE table SET active = 1 WHERE id IN (1,4,12,55,111)
its inside a transaction, cause i'm updating something else in this process.
the engine is InnoDB
My problem:
Someone told me that doing such a query is equivalent to 5 queries at execution, cause the IN will translate to the a given number of OR, and run them one after another.
eventually, instead of 1 i get N which is the number in the IN.
he suggests to create a temp table, insert all the new values in it, and then update by join.
Does he right? both of the equivalency and performance.
What do you suggest? i've thought INSERT INTO .. ON DUPLICATE UPDATE will help but i don't have all the data for the row, only it id, and that i want to set active = 1 on it.
Maybe this query is better?
UPDATE table SET
active = CASE
WHEN id='1' THEN '1'
WHEN id='4' THEN '1'
WHEN id='12' THEN '1'
WHEN id='55' THEN '1'
WHEN id='111' THEN '1'
ELSE active END
WHERE campaign_id > 0; //otherwise it throws an error about updating without where clause in safe mode, and i don't know if i could toggle safe mode off.
Thanks.
It's the other way around. OR can sometimes be turned into IN. IN is then efficiently executed, especially if there is an index on the column. If you have 1000 entries in the IN, it will do 1000 probes into the table based on id.
If you are running a new enough version of MySQL, I think you can do EXPLAIN EXTENDED UPDATE ...OR...; SHOW WARNINGS; to see this conversion;
The UPDATE CASE... will probably tediously check each and every row.
It would probably be better on other users of the system if you broke the UPDATE up into multiple UPDATEs, each having 100-1000 rows. More on chunking .
Where did you get the ids in the first place? If it was via a SELECT, then perhaps it would be practical to combine it with the UPDATE to make it one step instead of two.
I think below is better because it uses primary key.
UPDATE table SET active = 1 WHERE id<=5

Which statement is more efficient between with or without additional condition when updating a row in mysql

I am using mysql database, and now I must make sure that a value in a column should be 1 while it may be 1 already. So, considering the following two statements:
UPDATE category SET is_leaf=1 WHERE id=9
or
UPDATE category SET is_leaf=1 WHERE id=9 AND is_leaf=0
id is the primary key, the difference is when is_leaf is already 1, then to update it or not, which is more efficient?
I know it doesn't matter a lot, but I want to find out to better understanding mysql.
UPDATE category SET is_leaf=1 WHERE id=9 AND is_leaf=0
is more efficient. because then it update only relevant data. otherwise even if the is_leaf=1 records are also going to update.
Assume that there are 1000 record on the table and it take 1s to update one record. if u trying to update all records then it will take 1000 S. but assume in this scenario there are is_leaf=0 record count is 150 then if you use this second statement it will take only 150 seconds instead of 1000 s.
Edit :
Queries With Search Arguments (SARGs)
A WHERE clause helps you to restrict the number of rows returned by a query. However, the manner in which the WHERE condition is specified can impact the performance of the query. If the WHERE condition is written such that it uses a function that takes an indexed column as the input, then the index is ignored and the entire table is scanned. This results in performance degradation.
For example, the following results in a table scan because the column OrderDate is used in a function:
SELECT CustomerID, EmployeeID FROM Orders
WHERE DATEDIFF(m, OrderDate, GetDate())>3
If the function is rewritten as shown below, then the query seeks the required value using an index and this improves performance:
SELECT CustomerID, EmployeeID FROM Orders
WHERE OrderDate < DATEADD(m, -3, GetDate())
The filter criteria in the second query is said to use a Searchable Argument or SARG because the query optimizer can use an index seek operation during execution.
for more information about this you better read improving query performance
and also read this for Speeding up Searches and Filters
The query with the AND is_leaf=0 included can be more efficient sometimes.
It's not going to make much difference when locating the row based on the primary key. (The availability of an index on (id,is_leaf) might make a small difference.) But as soon as MySQL identifies that there is no row to be updated, it can take a shorter code path.
Absent that predicate, however, MySQL is going to have to locate the row, obtain a row lock (in the case of InnoDB), and fire any 'BEFORE UPDATE FOR EACH ROW' trigger. Then MySQL has to check if any column values are actually being changed (note that the execution of the trigger may be setting one or more columns to different values). If MySQL detects there is no change to the row, it can skip the setting of any 'ON UPDATE' timestamp column, fire off any 'AFTER UPDATE FOR EACH ROW' trigger, and set the affected rows count to zero. (In the context of a transaction, it's not clear if MySQL can release the row lock once it determines the row is not being changed, or whether a row lock will continue to be held until the commit or rollback.)
So, one big difference between the two statements is that MySQL will fire the 'FOR EACH ROW' triggers even if there are no actual changes to the row; but it won't fire any 'FOR EACH ROW' triggers for rows that are excluded by the WHERE clause.
In the simple case, absent any triggers, I don't expect there is any measurable difference in performance.
My personal preference is to include the extra predicate. This ensures that no (InnoDB) intent row locks will be requested or held, and no FOR EACH ROW triggers will be fired.
And apart from the row locking and trigger execution, as far as those two statements being exactly the same, they aren't really. At least not in the general case, where there is a possibility that is_leaf can contain a NULL or a value other than 0 or 1.
Given this statement:
UPDATE category SET is_leaf=1 WHERE id=9
For an equivalent statement that sets is_leaf to 1 whenever it is not already equal to 1, we would actually need to check for NULL and any value different than 1, such as:
UPDATE category SET is_leaf=1 WHERE id=9 AND NOT (is_leaf <=> 1)
Consider what happens when is_leaf is NULL or 2, for example, with this statement:
UPDATE category SET is_leaf=1 WHERE id=9 AND is_leaf=0

How can MySQL UPDATE more rows than specified?

I have an SQL UPDATE statement using the compound primary key (Key1,Key2) of a table that looks something like this:
UPDATE TableName SET FieldName = CASE
WHEN (Key1=389 AND Key2=5594091315209354374) THEN 1320243147187
WHEN (Key1=397 AND Key2=8686441440518828409) THEN 1320243147562
WHEN (Key1=389 AND Key2=5717973625907258381) THEN 1320243147182
....
WHEN (Key1=394 AND Key2=5512452777552926025) THEN 1320243147389 END
WHERE Key2 IN (123782199165241826,5594091315209354374,...,3553840348728167644)
AND Key1 IN (400,394,391,389,397);
I might have, say, 20 or so WHENs in the CASE statement.
How might MySQL say this has updated slightly more rows than there are WHENs?
Your CASE statement has nothing to do with which rows are affected. It's entirely up to your WHERE clause:
WHERE Key2 IN (123782199165241826,5594091315209354374,...,3553840348728167644)
AND Key1 IN (400,394,391,389,397);
Every row that fits those conditions will be updated. The question, then, is what happens to the rows that don't match a CASE condition?
For this part I'm not 100% sure what MySQL will do, as I'm more of a sql server guy. I suspect, however, that your CASE statement results in NULL, which is then assigned to FieldName. It's also possible that MySQL will decide not to change anything, but I would still expect it to report all the rows that match your WHERE clause as updated.
You should probably have an ELSE FieldName at the end of your case statement to be certain you get the latter behavior (no change) rather than the former (set to NULL).
I think the real determining factors are the values in your WHERE clause -- do these exactly correspond to the WHEN statements?

mySQL UPDATE query returns "0 rows affected"

I have this query:
UPDATE phonecalls
SET Called = "Yes"
WHERE PhoneNumber = "999 29-4655"
My table is phonecalls, I have a column named PhoneNumber. All I want to update is a column named Called to "yes".
Any idea what I am doing wrong? when I return my query it says 0 rows affected.
If the such value already exists, mysql won't change it and will therefore return "0 rows affected". So be sure to also check the current value of called
Another reason for 0 affected rows that I have observed: wrong data type. If the column you want to update is an integer or boolean, and you set it to a string, it won't be updated - but you will also get no error.
To sum up the other strategies/ideas from this post:
Check with a SELECT statement, whether your WHERE works and returns results.
Check whether your columns do already have the value you want to set.
Check if your desired value suits the data type of the column.
If the values are the same, MySQL will not update the row (without triggering any warning or error), so the affected row count will be 0.
The problem might be that there are no records with PhoneNumber == "999 29-4655".
Try this query:
SELECT * FROM phonecalls where PhoneNumber = '999 29-4655'
If it doesn't return anything, then there are no rows that match.
For the benefit of anyone here from Google, this problem was caused by me because I was trying to append to an empty field using CONCAT().
UPDATE example SET data=CONCAT(data, 'more');
If data is NULL, then CONCAT() returns NULL (ignoring the second parameter), so the value does not change (updating a NULL value to be a NULL value), hence the 0 rows updated.
In this case changing to the CONCAT_WS() function instead fixed the problem.
Try select count(*) from phonecalls where PhoneNumber = "999 29-4655"; That will give you the number of matching rows. If the result is 0, then there isn't a row in the database that matches.-
Check to make sure this returns some result.
SELECT * FROM phonecalls WHERE PhoneNumber = '999 29-4655'
If it doesn't return any result than the filter WHERE PhoneNumber = '999 29-4655' is not correct.
Does it say Rows matched: 1 Changed: 0 Warnings: 0? Then maybe it's already set to that value.
Did you try single quotes vs. double quotes?
"999 29-4655" is the space a space or a tab and is it consistent in your query and the database?
That's my sugestion:
UPDATE `phonecalls` SET `Called` = 'yeah!' WHERE `PhoneNumber` = '999 29-4655' AND `Called` != 'yeah!'
And make sure with the case-sensitive name of table and field`s.
Just ran into an obscure case of this. Our code reads a list of records from the database, changes a column, and writes them back one by one. The UPDATE's WHERE clause contains only two conditions: WHERE key=? AND last_update_dt=?. (The timestamp check is for optimistic locking: if the record is changed by another process before we write ours, 0 rows are updated and we throw an error.)
But for one particular row the UPDATE was failing- zero rows effected.
After much hair-pulling I noticed that the timestamp for the row was 2019-03-10 02:59. In much of the U.S. that timestamp wouldn't exist- Daylight Savings Time causes the time to skip directly from 2:00 to 3:00. So I guessed that during the round trip from MySQL to Java back to MySQL, some part of the code was interpreting that timestamp differently from the rest, making the timestamps in the WHERE clause not match.
Changing the row's timestamp by one hour avoided the problem.
(Of course, the correct fix is to abolish Daylight Savings Time. I created a Jira but the U.S. Government has not responded to it yet.)
In my case, I was trying to update a column of text to correct a truncation problem with it. Trying to update to the correct text was yielding 0 rows updated because the text in the row wasn't changing.
Once I extended the column in the table structure to accommodate for the correct number of characters, I was able to see the desired results.