-
Notifications
You must be signed in to change notification settings - Fork 28
[Proposal?] UpdateOrCreate -> Performance #1090
Comments
Mysql's "INSERT ... ON DUPLICATE KEY UPDATE" (or UPSERT for short) requires a unique index or a primary key, and there's some quirks in what happens when you have multiple unique indexes. The existing Laravel solution has no dependency on any indexes, and you can check for any column values you want. This means that we cannot replicate the existing Laravel functionality with an upsert without making some large assumptions about the database structure. |
I understood perfectly and what we have really is sensational. |
The issue title talks about performance - but it's not just that, it's about integrity; especially with concurrency. Not sure what I've in mind matches what the idea here is, but proper upsert support would be very handy sometimes. I can't talk about MySQL, but Postgres has Given the cases I encountered, I would imagine an interface like this:
Problems I see:
|
Further:
Then, how do get the last "inserted or updated (!)" id back?
|
This is my draft for the query builder implementation: staudenmeir/framework@8219335 Possible values for
What should the method return? Just a Boolean value or the number of affected rows? Is that useful? Example: Schema::create('stats', function ($table) {
$table->unsignedInteger('post_id');
$table->date('date');
$table->unsignedInteger('views');
$table->timestamps();
$table->unique(['post_id', 'date']);
});
DB::table('stats')->upsert(
[
['post_id' => 1, 'date' => now(), 'views' => 1, 'created_at' => now(), 'updated_at' => now()],
['post_id' => 2, 'date' => now(), 'views' => 1, 'created_at' => now(), 'updated_at' => now()],
],
['views' => DB::raw('stats.views + 1'), 'updated_at'],
['post_id', 'date']
);
sleep(1);
DB::table('stats')->upsert(
[
['post_id' => 2, 'date' => now(), 'views' => 1, 'created_at' => now(), 'updated_at' => now()],
],
['views' => DB::raw('stats.views + 1'), 'updated_at'],
['post_id', 'date']
); |
What would the Eloquent implementation look like? Unlike Are there actually real-life cases where you would use |
Unfortunately I won't be able to take a closer look for the next weeks due to work+vacation, sorry! |
After laravel/framework#28420, I've decided to release the code as a package: https://github.com/staudenmeir/laravel-upsert There is no support for |
I have thought about the performance of UpdateOrCreate and from what I could understand, this work seems to be more efficient if performed by the database itself.
From what I've seen, our
Database\Query\Builder
class performs this work by itself, that is, treating the process with two queries and validation internally.I do not know exactly how much this can be worth considering the flexibility we need to have in the framework, but I'd like to propose to you a REPLACE and DUPLICATE KEY UPDATE reading in MYSQL queries.
https://dev.mysql.com/doc/refman/5.7/en/replace.html
https://dev.mysql.com/doc/refman/5.7/en/insert-on-duplicate.html
My analysis is based on the premise of working with a data volume with UpdateOrCreate routines for about 50,000 lines, a task repeated many times a day. In current form, I believe I'm running twice as many operations at the application layer because of the need for verification.
We have as reference a native functionality of MongoDB, to improve the compression, see:
https://stackoverflow.com/questions/21342747/how-to-update-if-exists-otherwise-insert-new-document
The text was updated successfully, but these errors were encountered: