3

I'am using php on server side to manage data with MySQL. I have to request a API that gives me an list of users. I need to check for each user if he is in the database. If yes, I update his information. If not, I insert him in the data base.

The issue is that there is more than 2000+ users each times and my code in PHP is really slow (sometimes I get 504 Gateway Time-out). We will have even more users very soon.

How can I make my code faster ? Is Php ok ?

EDIT my codeV3 after improvement:

    $userList = getFromAPI();

      foreach ($userList as $userId){

        $db = dbConnect();


  $tagList = implode(",", $user["tagid_list"]);



          $query = $db->prepare(
      "INSERT INTO USERS(id, name, group) VALUES(:id, :name, :group)
       ON DUPLICATE KEY UPDATE name=values(name), group=values(group)"
          );

          $query->execute([
        "id"=>$id,
        "name"=>$name,
        "group"=>$group
          ]);
        }
7
  • 1
    I guess your Problem are the database statements. Commented Jul 3, 2017 at 8:56
  • 2
    Have you considered select id from users where id = :userid and seeing if it returns a row? Alternatively, how about scrapping that whole bit and instead doing insert into users ... on duplicate key update ...? Commented Jul 3, 2017 at 8:56
  • Don't fetch every single user when checking to see if specific user exists on the database, modify your select to select by the id that you want to check.... then you can also eliminate that array_column() and in_array() check Commented Jul 3, 2017 at 8:57
  • @NiettheDarkAbsol I make a updateEdit of my post with my new code with insert into on duplicate key update. But it seems not working. the "id" column is my primary key. Commented Jul 3, 2017 at 9:37
  • @MarkBaker Thank for the suggestion, I've modify the select and put a "!empty()" to check if there is result. Edited post with my new code if you have any improvement Commented Jul 3, 2017 at 9:38

3 Answers 3

4

Maybe try with putting $db = dbConnect(); outside of your foreach? I don't know if it is needed to open the connection in each cycle. It may be time consuming aswell.

Sign up to request clarification or add additional context in comments.

3 Comments

It depends on what that function does. If it returns a singleton, it doesn't matter (even if it still makes more sense to have it outside). If it actually connects in each iteration, then yes, that would definitely matter. There are other, way more, obvious things that affects the speed in that code, though.
The foreach you see is in an other function. So I should put $db = dbConnect out the function and put $db in parameters for this one ?
Yes, that is possible. You can also read about this in this question
3

You can use a single query for that:

INSERT INTO users (id, name)
VALUES (1, 'Alice'), (2, 'Bob'), (3, 'Cecil')
ON DUPLICATE KEY UPDATE name = VALUES(name);

In a nutshell: you insert new rows, but if one already exists (the key is duplicated), it is updated instead. You can build your insert values in a loop so you end up with a single query instead of 4000+.

Read more here.

5 Comments

$query = $db->prepare( "INSERT INTO USERS(id, name, group) VALUES(:id, :name, :group) ON DUPLICATE KEY UPDATE name=:name, group=:group");. Not seems to work.
That's awful! Maybe if you give some details about what's wrong, what error message you're getting, etc., then I can try to guess what the issue is.
There is no error message, but the data aren't insert or update.
Try building your query the way I suggested, using VALUES(name) and VALUES(group) in the update part. Do not repeat the same parametre twice.
Ok, it's done, but still no error msg and no data insert or update. (edited the post)
2

First of all get fetching all users ids from database out of foreach lopp and buffer it in some variable. Should be better.

4 Comments

Thanks, I replaced the fetch all users by a select where id=id. Is it better?
I would put fetchall before foreach and do not connect to db each cycle as @carl-kroeger-ihl noticed.
I delete the select, found a alternative way to do this. For the dbConnect() the issue is that all the code you see in the foreach is in a function. So I need to transfer the db in parameters?
I would to it like you've said (connected $db as function parameter).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.