categories

main
Johnathan Douglas 2023-07-13 17:17:49 -03:00
parent b3fed6b545
commit cd4ea422e3
19 changed files with 1068 additions and 84 deletions

View File

@ -41,7 +41,7 @@ class UpdateMassiveCommand extends Command
* 100000 - App\Jobs\UpdateMassive1Job ....... 2m 36s DONE
* 1000000 - App\Jobs\UpdateMassive1Job ...... 26m 10s DONE
*/
new UpdateMassive1Job(),
// new UpdateMassive1Job(),
/**
* Atualiza o campo data e valor, mas passando todos os ids das transações,
@ -52,7 +52,7 @@ class UpdateMassiveCommand extends Command
* 100000 - App\Jobs\UpdateMassive2Job ........... 1s DONE
* 1000000 - App\Jobs\UpdateMassive2Job .......... 15s DONE
*/
new UpdateMassive2Job(),
// new UpdateMassive2Job(),
/**
* Atualiza o campo data e valor, mas o campo data será preenchido com um valor diferente para cada transação,
@ -63,7 +63,7 @@ class UpdateMassiveCommand extends Command
* 100000 - App\Jobs\UpdateMassive3Job ....... 2m 44s DONE
* 1000000 - App\Jobs\UpdateMassive3Job ...... 27m 10s DONE
*/
new UpdateMassive3Job(),
// new UpdateMassive3Job(),
/**
* Atualiza o campo data e valor, mas o campo data será preenchido com um valor diferente para cada transação,
@ -74,7 +74,7 @@ class UpdateMassiveCommand extends Command
* 100000 - App\Jobs\UpdateMassive4Job .......... 8s DONE
* 1000000 - App\Jobs\UpdateMassive4Job ...... 1m 15s DONE
*/
new UpdateMassive4Job(),
// new UpdateMassive4Job(),
/**
* Atualiza o campo data e valor, mas o campo data será preenchido com um valor diferente para cada transação,

View File

@ -0,0 +1,53 @@
<?php
namespace App\Database;
use Illuminate\Database\Connection;
use Illuminate\Database\Query\Builder;
use Illuminate\Support\ServiceProvider;
class DatabaseMassUpdateServiceProvider extends ServiceProvider
{
/**
* Bootstrap the application events.
*
* @return void
*/
public function boot()
{
}
/**
* Register the service provider.
*
* @return void
*/
public function register()
{
Connection::resolverFor('pgsql', function ($connection, $database, $prefix, $config) {
return new PostgresConnection($connection, $database, $prefix, $config);
});
// Builder::macro('massUpdateWithFrom', function (array $values, string $uniqueBy = 'id') {
// $this->applyBeforeQueryCallbacks();
//
// $sql = $this->grammar->compileMassUpdateWithFrom($this, $values, $uniqueBy);
//
// return $this->connection->massUpdate($sql, $this->cleanBindings(
// $this->grammar->prepareBindingsForMassUpdateWithFrom($this->bindings, $values)
// ));
// });
Builder::macro('joinFrom', function (array $items, $tableAlias, $first, $operator = null, $second = null, $type = 'inner', $where = false) {
$table = $this->grammar->compileJoinFrom($this, $items, $tableAlias);
$bindings = $this->grammar->prepareBindingsJoinFrom($items);
$this->addBinding($bindings, 'join');
return $this->join($this->raw($table), $first, $operator, $second, $type, $where);
});
}
}

View File

@ -0,0 +1,115 @@
<?php
namespace App\Database;
use Faker\Factory as FakerFactory;
use Faker\Generator as FakerGenerator;
use Illuminate\Contracts\Queue\EntityResolver;
use Illuminate\Database\Connectors\ConnectionFactory;
use Illuminate\Database\DatabaseManager;
use Illuminate\Database\DatabaseTransactionsManager;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\QueueEntityResolver;
use Illuminate\Support\ServiceProvider;
class DatabaseServiceProvider extends ServiceProvider
{
/**
* The array of resolved Faker instances.
*
* @var array
*/
protected static $fakers = [];
/**
* Bootstrap the application events.
*
* @return void
*/
public function boot()
{
Model::setConnectionResolver($this->app['db']);
Model::setEventDispatcher($this->app['events']);
}
/**
* Register the service provider.
*
* @return void
*/
public function register()
{
Model::clearBootedModels();
$this->registerConnectionServices();
$this->registerEloquentFactory();
$this->registerQueueableEntityResolver();
}
/**
* Register the primary database bindings.
*
* @return void
*/
protected function registerConnectionServices()
{
// The connection factory is used to create the actual connection instances on
// the database. We will inject the factory into the manager so that it may
// make the connections while they are actually needed and not of before.
$this->app->singleton('db.factory', function ($app) {
return new ConnectionFactory($app);
});
// The database manager is used to resolve various connections, since multiple
// connections might be managed. It also implements the connection resolver
// interface which may be used by other components requiring connections.
$this->app->singleton('db', function ($app) {
return new DatabaseManager($app, $app['db.factory']);
});
$this->app->bind('db.connection', function ($app) {
return $app['db']->connection();
});
$this->app->bind('db.schema', function ($app) {
return $app['db']->connection()->getSchemaBuilder();
});
$this->app->singleton('db.transactions', function ($app) {
return new DatabaseTransactionsManager;
});
}
/**
* Register the Eloquent factory instance in the container.
*
* @return void
*/
protected function registerEloquentFactory()
{
$this->app->singleton(FakerGenerator::class, function ($app, $parameters) {
$locale = $parameters['locale'] ?? $app['config']->get('app.faker_locale', 'en_US');
if (! isset(static::$fakers[$locale])) {
static::$fakers[$locale] = FakerFactory::create($locale);
}
static::$fakers[$locale]->unique(true);
return static::$fakers[$locale];
});
}
/**
* Register the queueable entity resolver implementation.
*
* @return void
*/
protected function registerQueueableEntityResolver()
{
$this->app->singleton(EntityResolver::class, function () {
return new QueueEntityResolver;
});
}
}

View File

@ -0,0 +1,22 @@
<?php
namespace App\Database;
use App\Database\Query\Grammars\PostgresGrammar as QueryGrammar;
use Illuminate\Database\PostgresConnection as BaseDatabase;
class PostgresConnection extends BaseDatabase
{
protected function getDefaultQueryGrammar()
{
($grammar = new QueryGrammar)->setConnection($this);
return $this->withTablePrefix($grammar);
}
public function massUpdate($query, $bindings = [])
{
// dd($query, $bindings);
return $this->affectingStatement($query, $bindings);
}
}

View File

@ -0,0 +1,180 @@
<?php
namespace App\Database\Query\Grammars;
use Illuminate\Database\Query\Builder;
use Illuminate\Database\Query\Grammars\PostgresGrammar as BasePostgresGrammar;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;
class PostgresGrammar extends BasePostgresGrammar
{
public function getTableOrAlias(Builder $query)
{
return last(preg_split('/\s+as\s+/i', $query->from));
}
public function getTableName(Builder $query)
{
return current(preg_split('/\s+as\s+/i', $query->from));
}
/**
* @param array $items
*
* Ex:
* update transactions as t
* set
* date = c.date,
* value = c.value
* from ( values
* (1, '2023-01-05 00:00:00'::timestamp, 23.44),
* (2, '2023-01-03 00:00:00'::timestamp, 23.44)
* ) as c (id, date, value)
* where t.id = c.id";
* @throws \Exception
*/
public function compileMassUpdateWithFrom(Builder $query, array $items, string $uniqueBy = 'id')
{
if (count($items) === 0) {
throw new \Exception('values is empty');
}
$table = $this->wrapTable($query->from);
$tableName = $this->getTableName($query);
$tableOrAlias = $this->getTableOrAlias($query);
$tableAuxName = 'mu';
$properties = array_keys($items[0]);
$columnTypes = $this->getColumnTypes($tableName, $properties);
$columnsSql = [
// $this->wrap('type') . ' = ("mu"."id"::int + "t"."type" + 2)::int',
// $this->wrap('status') . ' = (case "mu"."id"::int when 1 then \'paid\' end)::text',
];
foreach ($properties as $property) {
if ($property !== $uniqueBy) {
$columnsSql[] = $this->wrap($property) . ' = ' . $this->wrap("$tableAuxName.$property") . '::' . $columnTypes[$property];
}
}
$columns = implode(', ', $columnsSql);
$parameters = [];
foreach ($items as $item) {
if (!isset($item[$uniqueBy])) {
throw new \Exception('column \'' . $uniqueBy . '\' not found');
}
$parametersItem = [];
foreach ($properties as $property) {
$parametersItem[] = $this->parameter($item[$property]);
}
$parameters[] = '(' . implode(', ', $parametersItem) . ')';
}
$parameters = implode(', ', $parameters);
$parametersColumns = implode(', ', $properties);
$from = " from (values $parameters) as $tableAuxName ($parametersColumns)";
$query->where("$tableOrAlias.$uniqueBy", '=', $query->raw($this->wrap("$tableAuxName.$uniqueBy") . '::' . $columnTypes[$uniqueBy]));
$where = $this->compileWheres($query);
return "update {$table} set {$columns}{$from} {$where}";
}
public function prepareBindingsForMassUpdateWithFrom(array $bindings, array $items)
{
$properties = array_keys($items[0]);
$values = [];
foreach ($items as $item) {
foreach ($properties as $property) {
$values[] = $item[$property];
}
}
$values = collect($values)
->map(function ($value, $column) {
return is_array($value) || ($this->isJsonSelector($column) && !$this->isExpression($value))
? json_encode($value)
: $value;
})
->all();
$cleanBindings = Arr::except($bindings, 'select');
return array_values(
array_merge($values, Arr::flatten($cleanBindings))
);
}
private function getColumnTypes(string $tableName, array $columns): array
{
$key = vsprintf('column;types;%s;%s', [
$tableName,
implode(';', $columns)
]);
return Cache::store('array')->rememberForever($key, function () use ($tableName, $columns) {
$schemaColumns = DB::table('information_schema.columns')
->select([
'column_name',
'udt_name',
])
->where('table_name', '=', $tableName)
->whereIn('column_name', $columns)
->get();
$types = [];
foreach ($schemaColumns as $schemaColumn) {
$types[$schemaColumn->column_name] = $schemaColumn->udt_name;
}
return $types;
});
}
public function compileJoinFrom(Builder $query, array $items, $tableAlias)
{
if (count($items) === 0) {
throw new \Exception('items is empty');
}
$values = [];
$properties = array_keys($items[0]);
foreach ($items as $item) {
$valuesItem = [];
foreach ($properties as $property) {
$valuesItem[] = $this->parameter($item[$property]);
}
$values[] = '(' . implode(', ', $valuesItem) . ')';
}
$values = implode(', ', $values);
$properties = implode(', ', $properties);
return "(values $values) as $tableAlias ($properties)";
}
public function prepareBindingsJoinFrom(array $items)
{
$values = [];
$properties = array_keys($items[0]);
foreach ($items as $item) {
foreach ($properties as $property) {
$values[] = $item[$property];
}
}
return $values;
}
}

View File

@ -0,0 +1,9 @@
<?php
namespace App\Database\Schema;
use Illuminate\Database\Schema\PostgresBuilder as BasePostgresBuilder;
class PostgresBuilder extends BasePostgresBuilder
{
}

View File

@ -4,6 +4,7 @@ namespace App\Database;
use Illuminate\Database\DatabaseManager;
use Illuminate\Database\Query\Expression;
use Illuminate\Support\Facades\DB;
class UpdateMassive4
{
@ -71,11 +72,17 @@ class UpdateMassive4
return;
}
// $db->enableQueryLog();
// DB::table('t_maquinetas as (,....)')
// ->join( 'from ()')
// UPDATE t_maquinetas
//SET t_terminal_id = sub.id
// FROM (SELECT id, id_antigo FROM t_terminal WHERE tipo = 1) as sub
//WHERE sub.id_antigo = t_pos_id AND
// (t_pdv_id IS NULL);
$db->table($table)
->whereIn($primaryKeyName, $primaryKeyValues)
->update($values);
// dd($db->getQueryLog());
}
}

View File

@ -0,0 +1,26 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
/**
* @property int id
* @property string name
*/
class Category extends Model
{
use HasFactory;
protected $table = 'categories';
/**
* The attributes that are mass assignable.
*
* @var array<int, string>
*/
protected $fillable = [
'name',
];
}

View File

@ -5,6 +5,12 @@ namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
/**
* @property int id
* @property int date
*
* @property int idade
*/
class Transaction extends Model
{
use HasFactory;
@ -37,4 +43,6 @@ class Transaction extends Model
protected $casts = [
'date' => 'datetime',
];
}

View File

@ -4,26 +4,36 @@ namespace App\Tasks;
use App\Models\Transaction;
use Carbon\Carbon;
use Illuminate\Support\Facades\DB;
class UpdateMassive1Task
{
public function handle()
{
Transaction::query()
->select([
'id',
])
->where('id', '>', 0)
->chunkById(1000, function ($transactions) {
foreach ($transactions as $transaction) {
Transaction::query()
->where('id', '=', $transaction->id)
->update([
'date' => Carbon::now(),
'value' => 1,
]);
}
// DB::beginTransaction();
// try {
foreach ($transactions as $transaction) {
Transaction::query()
->where('id', '=', $transaction->id)
->update([
'date' => Carbon::now(),
'value' => 1,
]);
}
DB::commit();
// } catch (\Exception $exception) {
// DB::rollBack();
// }
});
}

View File

@ -2,10 +2,10 @@
namespace App\Tasks;
use App\Database\UpdateMassive5;
use App\Models\Transaction;
use Carbon\Carbon;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\DB;
class UpdateMassive5Task
{
@ -20,22 +20,235 @@ class UpdateMassive5Task
->where('id', '>', 0)
->chunkById(1000, function ($transactions) {
$values = [];
/** @var Collection $transactions */
foreach ($transactions as $transaction) {
$transaction->date = Carbon::now()->subDays(random_int(1, 3));
$transaction->value = 10 + random_int(0, 10);
$config[] = [
'primary_key' => $transaction->id,
'columns' => [
'date' => "'$transaction->date'::timestamp",
'value' => $transaction->value,
]
// $values[] = [
// 'primary_key' => $transaction->id,
// 'columns' => [
// 'date' => "'$transaction->date'::timestamp",
// 'value' => $transaction->value,
// ]
// ];
$values[] = [
'id' => $transaction->id,
'date' => $transaction->date,
'value' => $transaction->value,
];
}
$updateMassive2 = new UpdateMassive5();
$updateMassive2->apply('transactions', 'id', $config);
// $values = [
// [
// 'id' => 1,
// 'date' => Carbon::now(),
// 'value' => 10,
// ],
// [
// 'id' => 2,
// 'date' => '2023-01-02',
// 'value' => 20,
//// 'value' => DB::raw('t.value + 1'),
// ]
// ];
//
// $values = [
//// [
//// 'id' => DB::raw('1::int8'),
//// 'date' => DB::raw('\'' . Carbon::now()->format('Y-m-d H:i:s') . '\'::timestamp'),
//// 'value' => DB::raw('10::numeric'),
//// ],
// [
// 'id' => 2,
// 'date' => '2023-01-02',
// 'value' => 20,
//// 'value' => DB::raw('t.value + 1'),
// ]
// ];
DB::enableQueryLog();
// DB::table('transactions')
// ->insert($values);
$values = [
[
'id' => 1,
'value' => 20,
// 'day' => 2,
],
[
'id' => 2,
'value' => 30,
// 'day' => 5,
],
[
'value' => 30,
'id' => 3,
// 'day' => 3,
],
];
DB::table('transactions as t')
->joinFrom($values, 'm', DB::raw('m.id::bigint'), '=', 't.id')
->updateFrom([
'value' => DB::raw('m.value::decimal'),
]);
DB::table('transactions as t')
->massUpdate([
[
'id' => 1,
'value' => DB::raw('20::float'),
'date' => '2023-01-01',
],
[
'id' => 2,
'value' => 30,
'date' => '2023-01-01',
],
[
'id' => 1,
'value' => 30,
'date' => '2023-01-01',
],
], 'id');
// $properties = array_keys($values[0]);
// $x = [];
// $propertiesCount = count($properties);
// foreach ($values as $item) {
// foreach ($properties as $property) {
// if (count(array_keys($item)) !== $propertiesCount) {
// throw new \Exception('a quantidade de propriedades é diferente');
// }
//
// $x [] = $item[$property];
// }
// }
//
//// dd($x);
//// DB::table('transactions as t')
//// ->massUpdate($values, $uniqueKeys = ['id', 'value'], );
//
// DB::table('transaction as t')
// ->whereIn('id', [1,2,3])
// ->update([
// 'value'=> DB::raw('value + (case id when 1 then 2.0 when 2 then 5.0 when 3 then 2.32 end)')
// ]);
// $table = DB::raw('(values (?, ?), (?, ?), (?, ?)) as "m" (' . implode(', ', $properties) . ')');
DB::enableQueryLog();
DB::table('transactions as t')
// ->join($table, DB::raw('m.id::bigint'), '=', 't.id')
// ->addBinding($x)
->joinFrom($values, 'm', DB::raw('m.id::bigint'), '=', 't.id')
// ->where('t.date', '>', Carbon::now()->subDays(5))
->updateFrom([
// "value" => DB::raw('t.value + "m"."value"::decimal'),
// "date" => DB::raw('(t.date::timestamp + (interval \'1\' day * m.day::int))'),
"value" => DB::raw('m.value::decimal'),
]);
dd(DB::getQueryLog());
dd('aa');
// t.value = m.value + 1;
// t.value = m.value + 1;
DB::table('transactions as t')
->joinFrom($values, 'm', DB::raw('m.id::bigint'), '=', 't.id')
->updateFrom([
'value' => DB::raw('m.value::decimal'),
]);
dd(DB::getQueryLog());
$values = [
[
'id' => 1,
'date' => Carbon::now(),
'value' => 20,
],
[
'id' => 2,
'date' => '2023-01-02',
'value' => 30,
],
];
DB::table('transactions as t')
->joinFrom($values, 'm', DB::raw('m.id::bigint'), '=', 't.id')
->updateFrom([
'value' => DB::raw('(m.value::decimal + 1)::decimal'),
'date' => DB::raw('m.date::timestamp'),
'type' => 2,
'status' => DB::raw('case t.id when 1 then \'paid\' else t.status end'),
]);
// DB::table('transactions as t')
// ->join(DB::raw('(values (1,\'2019-01-15 10:00:00\',10), (2,\'2019-01-15 10:00:00\', 20) ) as mu (id, value, date)'), 'mu.id', '=', 't.id')
// ->updateFrom([
// 'value' => DB::raw('(mu.value::decimal + 1)::decimal'),
// 'date' => DB::raw('mu.date::timestamp'),
// 'type' => 2,
// 'status' => DB::raw('case t.id when 1 then \'paid\' else t.status end'),
// ]);
dd(DB::getQueryLog());
dd('aa');
// DB::table('transactions as t')
// ->massUpdateWithFrom(
// values: [
// [
// 'id' => 1,
// 'date' => Carbon::now(),
// 'value' => 10,
// ]
// ],
//// valuesAlias: 'mu',
//// updateColumns: [
//// 'date' => 'mu.date::timestamp',
//// 'value' => 'mu.value + 1',
//// 'type' => '2',
//// 'fee' => '(t.value / mu.value) * 0.1',
//// ]
// );
// $queryLog = DB::getQueryLog();
//
// $sql = $queryLog[1]['query'];
// $bindings = $queryLog[1]['bindings'];
//
// foreach ($bindings as $i => $binding) {
// if ($binding instanceof \DateTimeInterface) {
// $bindings[$i] = $binding->format('\'Y-m-d H:i:s\'');
// } else {
// $bindings[$i] = "'$binding'";
// }
// }
//
// $sql = vsprintf(str_replace('?', '%s', $sql), $bindings);
//
// dd($sql);
//
// dd('aa');
// $updateMassive2 = new UpdateMassive5();
// $updateMassive2->apply('transactions', 'id', $values);
});
}
}

View File

@ -7,6 +7,7 @@
"require": {
"php": "^8.1",
"guzzlehttp/guzzle": "^7.2",
"johdougss/laravel-mass-update": "^1.0",
"laravel/framework": "^10.10",
"laravel/sanctum": "^3.2",
"laravel/tinker": "^2.8"

92
composer.lock generated
View File

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "aa322c53454393ed775cfe4807d54a50",
"content-hash": "d147bec59f72c112c82016e4eaacc88b",
"packages": [
{
"name": "brick/math",
@ -975,17 +975,47 @@
"time": "2021-10-07T12:57:01+00:00"
},
{
"name": "laravel/framework",
"version": "v10.14.1",
"name": "johdougss/laravel-mass-update",
"version": "1.0.1",
"source": {
"type": "git",
"url": "https://github.com/laravel/framework.git",
"reference": "6f89a2b74b232d8bf2e1d9ed87e311841263dfcb"
"url": "https://github.com/johdougss/laravel-mass-update.git",
"reference": "4e8e7b0b960e6185108aecd19d351a5dd65296fc"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laravel/framework/zipball/6f89a2b74b232d8bf2e1d9ed87e311841263dfcb",
"reference": "6f89a2b74b232d8bf2e1d9ed87e311841263dfcb",
"url": "https://api.github.com/repos/johdougss/laravel-mass-update/zipball/4e8e7b0b960e6185108aecd19d351a5dd65296fc",
"reference": "4e8e7b0b960e6185108aecd19d351a5dd65296fc",
"shasum": ""
},
"require": {
"illuminate/database": "*"
},
"type": "library",
"autoload": {
"psr-4": {
"Johdougss\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"support": {
"issues": "https://github.com/johdougss/laravel-mass-update/issues",
"source": "https://github.com/johdougss/laravel-mass-update/tree/1.0.1"
},
"time": "2023-07-13T20:11:49+00:00"
},
{
"name": "laravel/framework",
"version": "v10.15.0",
"source": {
"type": "git",
"url": "https://github.com/laravel/framework.git",
"reference": "c7599dc92e04532824bafbd226c2936ce6a905b8"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laravel/framework/zipball/c7599dc92e04532824bafbd226c2936ce6a905b8",
"reference": "c7599dc92e04532824bafbd226c2936ce6a905b8",
"shasum": ""
},
"require": {
@ -1172,7 +1202,7 @@
"issues": "https://github.com/laravel/framework/issues",
"source": "https://github.com/laravel/framework"
},
"time": "2023-06-28T14:25:16+00:00"
"time": "2023-07-11T13:43:52+00:00"
},
{
"name": "laravel/sanctum",
@ -5578,16 +5608,16 @@
},
{
"name": "filp/whoops",
"version": "2.15.2",
"version": "2.15.3",
"source": {
"type": "git",
"url": "https://github.com/filp/whoops.git",
"reference": "aac9304c5ed61bf7b1b7a6064bf9806ab842ce73"
"reference": "c83e88a30524f9360b11f585f71e6b17313b7187"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/filp/whoops/zipball/aac9304c5ed61bf7b1b7a6064bf9806ab842ce73",
"reference": "aac9304c5ed61bf7b1b7a6064bf9806ab842ce73",
"url": "https://api.github.com/repos/filp/whoops/zipball/c83e88a30524f9360b11f585f71e6b17313b7187",
"reference": "c83e88a30524f9360b11f585f71e6b17313b7187",
"shasum": ""
},
"require": {
@ -5637,7 +5667,7 @@
],
"support": {
"issues": "https://github.com/filp/whoops/issues",
"source": "https://github.com/filp/whoops/tree/2.15.2"
"source": "https://github.com/filp/whoops/tree/2.15.3"
},
"funding": [
{
@ -5645,7 +5675,7 @@
"type": "github"
}
],
"time": "2023-04-12T12:00:00+00:00"
"time": "2023-07-13T12:00:00+00:00"
},
{
"name": "hamcrest/hamcrest-php",
@ -5700,16 +5730,16 @@
},
{
"name": "laravel/pint",
"version": "v1.10.3",
"version": "v1.10.4",
"source": {
"type": "git",
"url": "https://github.com/laravel/pint.git",
"reference": "c472786bca01e4812a9bb7933b23edfc5b6877b7"
"reference": "f56798088068af8bd75a8f2c4ecae022990fdf75"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laravel/pint/zipball/c472786bca01e4812a9bb7933b23edfc5b6877b7",
"reference": "c472786bca01e4812a9bb7933b23edfc5b6877b7",
"url": "https://api.github.com/repos/laravel/pint/zipball/f56798088068af8bd75a8f2c4ecae022990fdf75",
"reference": "f56798088068af8bd75a8f2c4ecae022990fdf75",
"shasum": ""
},
"require": {
@ -5720,7 +5750,7 @@
"php": "^8.1.0"
},
"require-dev": {
"friendsofphp/php-cs-fixer": "^3.18.0",
"friendsofphp/php-cs-fixer": "^3.21.1",
"illuminate/view": "^10.5.1",
"laravel-zero/framework": "^10.0.2",
"mockery/mockery": "^1.5.1",
@ -5762,20 +5792,20 @@
"issues": "https://github.com/laravel/pint/issues",
"source": "https://github.com/laravel/pint"
},
"time": "2023-06-20T15:55:03+00:00"
"time": "2023-07-11T15:18:27+00:00"
},
{
"name": "laravel/sail",
"version": "v1.23.0",
"version": "v1.23.1",
"source": {
"type": "git",
"url": "https://github.com/laravel/sail.git",
"reference": "a2e046f748e87d3ef8b2b381e0e5c5a11f34e46b"
"reference": "62582606f80466aa81fba40b193b289106902853"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laravel/sail/zipball/a2e046f748e87d3ef8b2b381e0e5c5a11f34e46b",
"reference": "a2e046f748e87d3ef8b2b381e0e5c5a11f34e46b",
"url": "https://api.github.com/repos/laravel/sail/zipball/62582606f80466aa81fba40b193b289106902853",
"reference": "62582606f80466aa81fba40b193b289106902853",
"shasum": ""
},
"require": {
@ -5827,7 +5857,7 @@
"issues": "https://github.com/laravel/sail/issues",
"source": "https://github.com/laravel/sail"
},
"time": "2023-06-16T21:20:12+00:00"
"time": "2023-06-28T18:31:28+00:00"
},
{
"name": "mockery/mockery",
@ -6495,16 +6525,16 @@
},
{
"name": "phpunit/phpunit",
"version": "10.2.3",
"version": "10.2.4",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/phpunit.git",
"reference": "35c8cac1734ede2ae354a6644f7088356ff5b08e"
"reference": "68484779b5a2ed711fbdeba6ca01910d87acdff2"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/35c8cac1734ede2ae354a6644f7088356ff5b08e",
"reference": "35c8cac1734ede2ae354a6644f7088356ff5b08e",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/68484779b5a2ed711fbdeba6ca01910d87acdff2",
"reference": "68484779b5a2ed711fbdeba6ca01910d87acdff2",
"shasum": ""
},
"require": {
@ -6576,7 +6606,7 @@
"support": {
"issues": "https://github.com/sebastianbergmann/phpunit/issues",
"security": "https://github.com/sebastianbergmann/phpunit/security/policy",
"source": "https://github.com/sebastianbergmann/phpunit/tree/10.2.3"
"source": "https://github.com/sebastianbergmann/phpunit/tree/10.2.4"
},
"funding": [
{
@ -6592,7 +6622,7 @@
"type": "tidelift"
}
],
"time": "2023-06-30T06:17:38+00:00"
"time": "2023-07-10T04:06:08+00:00"
},
{
"name": "sebastian/cli-parser",

View File

@ -42,7 +42,7 @@ return [
|
*/
'debug' => (bool) env('APP_DEBUG', false),
'debug' => (bool)env('APP_DEBUG', false),
/*
|--------------------------------------------------------------------------
@ -168,6 +168,9 @@ return [
// App\Providers\BroadcastServiceProvider::class,
App\Providers\EventServiceProvider::class,
App\Providers\RouteServiceProvider::class,
App\Database\DatabaseMassUpdateServiceProvider::class,
// Johdougss\Database\DatabaseMassUpdateServiceProvider::class,
])->toArray(),
/*

View File

@ -0,0 +1,23 @@
<?php
namespace Database\Factories;
use Illuminate\Database\Eloquent\Factories\Factory;
/**
* @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\User>
*/
class CategoryFactory extends Factory
{
/**
* Define the model's default state.
*
* @return array<string, mixed>
*/
public function definition(): array
{
return [
'name' => 'category ' . fake()->numerify('######')
];
}
}

View File

@ -0,0 +1,27 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration {
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('categories', function (Blueprint $table) {
$table->id();
$table->string('name', 20);
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('categories');
}
};

View File

@ -5,6 +5,7 @@ use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration {
/**
* Run the migrations.
*/
@ -13,6 +14,9 @@ return new class extends Migration {
Schema::create('transactions', function (Blueprint $table) {
$table->id();
$table->decimal('value', 12, 2);
$table->integer('type')->default(1);
$table->string('status', 10)->default('pending');
$table->bigInteger('category_id')->nullable();
$table->timestamp('date');
$table->timestamps();
});

View File

@ -0,0 +1,19 @@
<?php
namespace Database\Seeders;
use App\Models\Transaction;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;
class CategorySeeder extends Seeder
{
/**
* Seed the application's database.
*/
public function run(): void
{
$categories = Transaction::factory(5)->make();
Transaction::query()->insert($categories->toArray());
}
}

View File

@ -4,6 +4,7 @@ namespace Database\Seeders;
use App\Models\Transaction;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;
class TransactionSeeder extends Seeder
{
@ -13,44 +14,262 @@ class TransactionSeeder extends Seeder
public function run(): void
{
$count = config('update-massive.items_count');
$type = 3;
if ($type === 1) {
/**
* insert unit
* 1000 - Database\Seeders\TransactionSeeder ...... 1,443.86 ms DONE
* 10000 - Database\Seeders\TransactionSeeder ..... 14,256.24 ms DONE
* 100000 - Database\Seeders\TransactionSeeder .... 158,413.75 ms DONE
* 1000000 -
*/
Transaction::factory($count)->create();
$this->type1($count);
}
if ($type === 2) {
/**
* insert multiple
* 1000 - Database\Seeders\TransactionSeeder ......... 96.11 ms DONE
* 10000 - Database\Seeders\TransactionSeeder ........ 887.48 ms DONE
* 100000 - SQLSTATE[HY000]: General error: 7 number of parameters must be between 0 and 65535
* 1000000 - SQLSTATE[HY000]: General error: 7 number of parameters must be between 0 and 65535
*/
$transactions = Transaction::factory($count)->make();
Transaction::query()->insert($transactions->toArray());
$this->type2($count);
}
if ($type === 3) {
$this->type3($count);
}
/**
* Limit insert sql string
* insert multiple block
*
* 1000 - Database\Seeders\TransactionSeeder ......... 97.71 ms DONE
* 10000 - Database\Seeders\TransactionSeeder ........ 833.27 ms DONE
* 100000 - Database\Seeders\TransactionSeeder ...... 8,256.29 ms DONE
* 1000000 - Database\Seeders\TransactionSeeder ..... 95,473.46 ms DONE
*/
if ($type === 4) {
$this->type4($count);
}
if ($type === 5) {
$this->type5($count);
}
if ($type === 6) {
$this->type6($count);
}
if ($type === 7) {
$this->type7($count);
}
}
/**
* @param mixed $count
* @return void
*/
public function type1(mixed $count): void
{
/**
* insert unit
* 1000 - Database\Seeders\TransactionSeeder ...... 1,443.86 ms DONE
* 10000 - Database\Seeders\TransactionSeeder ..... 14,256.24 ms DONE
* 100000 - Database\Seeders\TransactionSeeder .... 158,413.75 ms DONE
* 1000000 -
*
* 1. insert into transactions (id, value, date) values (1, 10, '2023-04-01');
* - reconstroi os indices, verifica chave, view materializada
*
* 2. insert into transactions (id, value, date) values (2, 20, '2023-04-02');
* - reconstroi os indices, verifica chave, view materializada
*/
// DB::enableQueryLog();
Transaction::factory($count)->create();
// dd(DB::getQueryLog());
// $result = DB::getQueryLog();
// dump(collect($result)->sum('time'));
}
/**
* @param mixed $count
*/
public function type2(mixed $count): void
{
/**
* insert multiple
* 1000 - Database\Seeders\TransactionSeeder ......... 96.11 ms DONE
* 10000 - Database\Seeders\TransactionSeeder ........ 887.48 ms DONE
* 100000 - SQLSTATE[HY000]: General error: 7 number of parameters must be between 0 and 65535
* 1000000 - SQLSTATE[HY000]: General error: 7 number of parameters must be between 0 and 65535
*/
$transactions = Transaction::factory($count)->make();
Transaction::query()->insert($transactions->toArray());
}
/**
* Limit insert sql string
* insert multiple block
*
* 1000 - Database\Seeders\TransactionSeeder ......... 97.71 ms DONE
* 10000 - Database\Seeders\TransactionSeeder ........ 833.27 ms DONE
* 100000 - Database\Seeders\TransactionSeeder ...... 8,256.29 ms DONE
* 1000000 - Database\Seeders\TransactionSeeder ..... 95,473.46 ms DONE
*/
private function type3(mixed $count)
{
$block = 1000;
while ($count > 0) {
if ($count < $block) {
$block = $count;
}
$transactions = Transaction::factory($block)->make();
Transaction::query()->insert($transactions->toArray());
// insert into values ( ...), (....), ... 1000
// commit
// insert into values ( ...), (....), ... 1000
// commit
// insert into values ( ...), (....), ... 1000
// commit
$count -= $block;
}
}
/**
* insert unit
* 1000 - Database\Seeders\TransactionSeeder ...... 391.11 ms DONE
* 10000 - Database\Seeders\TransactionSeeder ..... 3,741.94 ms DONE
* 100000 - Database\Seeders\TransactionSeeder .... 38,605.27 ms DONE
* 1000000 -
*
* 1. insert into transactions (id, value, date) values (1, 10, '2023-04-01');
* 2. insert into transactions (id, value, date) values (2, 20, '2023-04-02');
* .... 100.000
*
* - reconstroi os indices, verifica chave, view materializada
*/
private function type4(int $count)
{
DB::beginTransaction();
try {
Transaction::factory($count)->create();
DB::commit();
} catch (\Exception $exception) {
DB::rollBack();
}
}
/**
* insert unit
* 1000 - Database\Seeders\TransactionSeeder ...... 380.20 ms DONE
* 10000 - Database\Seeders\TransactionSeeder ..... 3,716.59 ms DONE
* 100000 - Database\Seeders\TransactionSeeder .... 39,143.04 ms DONE
* 1000000 -
*
* 1. insert into transactions (id, value, date) values (1, 10, '2023-04-01');
* 2. insert into transactions (id, value, date) values (2, 20, '2023-04-02');
* .... 1.000 commit
* - reconstroi os indices, verifica chave, view materializada
*
* 1001. insert into transactions (id, value, date) values (1, 10, '2023-04-01');
* 1002. insert into transactions (id, value, date) values (2, 20, '2023-04-02');
* .... 1.000 commit
* - reconstroi os indices, verifica chave, view materializada
*
*/
private function type5(mixed $count)
{
$block = 1000;
while ($count > 0) {
if ($count < $block) {
$block = $count;
}
DB::beginTransaction();
try {
Transaction::factory($block)->create();
DB::commit();
// echo 'commit' . PHP_EOL;
$count -= $block;
} catch (\Exception $exception) {
DB::rollBack();
}
}
}
/**
*
* PDO
* Prepared statement insert verificar
*
* PREPARE transactions_plan (decimal, timestamp) AS
* INSERT INTO transactions (value, date)
* VALUES ($1, $2);
*
* EXECUTE transactions_plan(23.44, '2023-01-05 00:00:00'::timestamp);
*
* 1000 - Database\Seeders\TransactionSeeder ...... 1,341.07 ms DONE
* 10000 - Database\Seeders\TransactionSeeder ..... 13,415.95 ms DONE
* 100000 - Database\Seeders\TransactionSeeder ............ - ms DONE
* 1000000 - Database\Seeders\TransactionSeeder ............ - ms DONE
*
* 1000 - Database\Seeders\TransactionSeeder ........ 173.91 ms DONE
* 10000 - Database\Seeders\TransactionSeeder ...... 1,591.86 ms DONE
* 100000 - Database\Seeders\TransactionSeeder ......16,331.67 ms DONE
* 1000000 - Database\Seeders\TransactionSeeder ............ - ms DONE
*
* @param mixed $count
* @return void
*/
private function type6(mixed $count)
{
// DB::enableQueryLog();
// DB::beginTransaction();
//
// try {
// DB::enableQueryLog();
$sql1 = 'PREPARE transactions_plan5 (decimal, timestamp) AS INSERT INTO transactions (value, date) VALUES ($1::decimal, $2::timestamp)';
DB::unprepared($sql1);
$transactions = Transaction::factory($count)->make();
// $sql2 = 'EXECUTE transactions_plan5 (?, ?)';
foreach ($transactions as $transaction) {
$sql3 = vsprintf('EXECUTE transactions_plan5 (%s, \'%s\')', [
(float)$transaction->value,
$transaction->date->format('Y-m-d H:i:s')
]);
DB::unprepared($sql3);
// $dateFormatted = $transaction->date->format('Y-m-d H:i:s');
// $bindings = [
// (float)$transaction->value,
// $dateFormatted,
// ];
// DB::statement($sql2, $bindings);
}
// dd(DB::getQueryLog());
// DB::commit();
// } catch (\Exception $exception) {
// DB::rollBack();
// }
// $result = DB::getQueryLog();
// dump(collect($result)->sum('time'));
}
/**
* Limit insert sql string
* insert multiple block
*
* 1000 - Database\Seeders\TransactionSeeder ......... 97.71 ms DONE
* 10000 - Database\Seeders\TransactionSeeder ........ 858.70 ms DONE
* 100000 - Database\Seeders\TransactionSeeder ...... 8,819.44 ms DONE
* 1000000 - Database\Seeders\TransactionSeeder ..... 87,649.37 ms DONE
*/
private function type7(mixed $count)
{
DB::beginTransaction();
try {
$block = 1000;
while ($count > 0) {
@ -62,8 +281,23 @@ class TransactionSeeder extends Seeder
$transactions = Transaction::factory($block)->make();
Transaction::query()->insert($transactions->toArray());
// insert into values ( ...), (....), ... 1000
// insert into values ( ...), (....), ... 1000
// insert into values ( ...), (....), ... 1000
$count -= $block;
}
DB::commit();
// commit
} catch (\Exception $exception) {
DB::rollBack();
}
}
private function champion($count)
{
$this->type3($count);
}
}