3

When I insert a post I've found that there is a slow call to wp_unique_post_slug from within insert_post (In the database I'm using to test there is 155,000 posts - live would have considerably more). As I don't believe a slug is important for what I'm doing (a person who is browsing our site will probably never see a single page view for this post type), is there anything I can do that can either speed up the call or (better yet) eliminate it.

Looking at the code for insert_post, I couldn't see a way of doing it without modifying core (which is something I'd rather not do). The code I'm using is:

$post = array(
    'post_title' => 'post_title',
    'post_type' => 'character',
    'post_status' => 'publish'
);
$post_id = wp_insert_post( $post );

Edit:

As it appears people are missing the information that I have written in this question. Here is the issue as clear as I can make it.

The Problem:

Slow performance. I have tracked this down to the function wp_unique_post_slug called from within wp_insert_post

The code that calls wp_insert_post:

$post = array(
    'post_title' => 'post_title',
    'post_type' => 'character',
    'post_status' => 'publish'
);

$post_id = wp_insert_post( $post );

(yes they are all strings and not variables being assigned to $post)

Other information:

The post status needs to be 'publish' as these posts are presented to the user (although not in the standard WordPress manner).

I could fix it by editing core, but this is a BAD idea for a number of reasons.

A slug is not important as the user shouldn't be going to a single page view of this content type.

  • Stay away from modifying core. You'll have that erased after every WordPress update. – kaiser Oct 22 '13 at 23:44
  • that, among a number of other reasons is the reason I'd rather not do it. – Brian Barnes Oct 23 '13 at 0:34
2

I know this is really old question, but today I was dealing with something similar, and I have found a solution - if wp_unique_post_slug() calling is performance bottleneck, and post_name value is not important, then set post_name manualy to some random value.

My wp_insert_post post action was taking too long lately (20-30s). It saves custom post type order not visible to visitors, with post_title = "Order" (post title does not matter). That resulted in thousands of posts with title "Order", and WP was automatically generating post names (post_name) as "order-1", "order-2", "order-3", ... "order-6152" ...

And with every wp_insert_post WP searched for free post name starting from "order" and incrementing suffixed number - and every step was one DB query. So in my case WP did more than 6,000 DB queries before inserting one post to database.

Setting random post_name in wp_insert_post() call disables wp_unique_post_slug() call.

1

Source inspection -> Abort cases

When you look at the source of wp_unique_post_slug(), then you'll see that the first two lines are

if ( 
    in_array( $post_status, 
        array( 'draft', 'pending', 'auto-draft' )
    )
    OR
    ( 
        'inherit' == $post_status 
        AND 'revision' == $post_type 
    )
)
    return $slug;

Which means that there's nothing calculated, queried or processed if

  • The post status is draft, pending or auto-draft

OR

  • The post status is inherit and the Post Type a revision

As you can see from the source of wp_insert_post() where wp_unique_post_slug() is called, it passes the status exactly as you did.

$post_name = wp_unique_post_slug(
    $post_name,
    $post_ID,
    $post_status,
    $post_type,
    $post_parent
);

Possible solution

In case a post type isn't public, but only visible from the admin UI, then you just have to ignore the post status, set it to draft, pending, whatever (when inserting the post) and you're fine and nothing will be processed.

Every other attempt will fail as $wpdb->get_var() has no filter.

MAYBE... solution

You can still use a drop in. A replacement for the $wpdb class/object. Just copy the contents of ~/wp-includes/wp-db.php into a new file named db.php and place it into your ~/wp-content (or whatever you named it) folder.

Then modify $wpdb->get_var() to abort in case it is called from the context of wp_unique_post_slug(). Then it depends on your creativity and skills if it's faster to abort that.

Keep in mind that you'll have to update that file every time there is a core update.

Notes:

  • If you leave the post_status argument empty, it automatically assigns draft.
  • For post post types, when no category is assigned, it automatically gets assigned the default category. But only if the post status isn't auto-draft.
  • If post_date_gmt is empty and you're adding a draft, then the value will automatically be set to '0000-00-00 00:00:00'.
  • If the post_name (title) is empty and the status is draft, auto-draft or pending, then the title will not get sanitized.
  • Don't set a publish date for now or earlier, as the status will get converted to "future" (in case the status still is "publish").
  • Thought that might be the case. The "possible" solution wont work in my case as there are other reasons why post_status needs to be publish. The "maybe" solution may work, but that will be a bit of plugging through debug_backtrace (or similar) as other posts need to be visible. ~/wp-content isn't overwritten when wordpress is updated (wordpress keeps it's plugins doesn't it). – Brian Barnes Oct 23 '13 at 0:45
  • @BrianBarnes Please go and edit your question. In this edit, specify all the reasons why your post status has to be published, if you're bulk inserting and if yes during which period and how, etc. Could still be that your problem is actually a "XY Problem". – kaiser Oct 23 '13 at 1:02
  • because 'publish' is published (and hence other code that I've written depends on this). 'draft' means that it isn't ready to be presented/published, 'trash' means it effectively deleted. While I am not presenting the data in a typical WordPress fashion, it is still presented to the user. – Brian Barnes Oct 23 '13 at 1:38
  • @BrianBarnes Still your explanation is extremely abstract. No idea what you're really after. If this query is your bottle neck, but other queries depend on "publish" post status, then you'll have to fix them as well. With the very limited current info I can't add anything more to this question. – kaiser Oct 23 '13 at 2:13
  • Please re-read my question. I state that the function call "wp_unique_post_slug" takes an excessive long time to run (there is a slow call to wp_unique_post_slug). This answer that you post does suggest 2 solutions (only 1 (the "maybe") which could work in my situation, but is rather complex to implement - I am hoping for something easier) which could help others in a similar situation. I want a solution (as my question states) that either does away with the call or speed it up (is there anything I can do that can either speed up the call or (better yet) eliminate it). – Brian Barnes Oct 23 '13 at 2:34

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.