Removing the first image in content

I don’t know of any plugin specifically for this, there’s nothing in WP that will do this but it’s not too difficult to implement with a little php, even 20k posts shouldn’t be too extreme. Depending on your server settings you may need to do some workarounds to make sure the connection stays alive but the basic idea would be to loop through all posts, check that it’s a proper post (not a page, revision, custom post_type, etc.) and then run a string replace on the content very much like the code you already have.

This is untested, just as an example:

$query = new WP_Query( array(
  'post_type' => 'post',
  'post_status' => 'publish'
) );

foreach ( $query->posts as $edit_post ) {
  $edit_post->post_content
  wp_update_post( array(
    'ID' => $edit_post->ID,
    'post_content' => preg_replace( "/<img[^>]+\>/i", "", $edit_post->post_content, 1 )
  );
}

You’d probably want to put that in a plugin of it’s own with some admin page code to run it someplace safe, hopefully you get the idea.

WP-CLI has the ability to do bulk edits with search-replace of DB strings and could probably be used to do something similar.

$ wp search-replace '/<img[^>]+\>/i' '' wp_posts --regex