singlestoredb/singlestoredb-laravel
Official SingleStoreDB driver for Laravel. Wraps Laravel’s MySQL support with SingleStore-specific Eloquent and migration features (columnstore/rowstore, shard & sort keys, sparse/temporary tables), JSON support, and query compatibility fixes, tested across versions.
Installation:
composer require singlestoredb/singlestoredb-laravel
Ensure pdo_mysql is enabled (php -i | grep pdo_mysql).
Configure Database:
Update config/database.php to use the singlestoredb driver:
'singlestoredb' => [
'driver' => 'singlestore',
'host' => env('DB_HOST'),
'database' => env('DB_DATABASE'),
'username' => env('DB_USERNAME'),
'password' => env('DB_PASSWORD'),
'charset' => 'utf8mb4',
'options' => [
PDO::ATTR_PERSISTENT => true, // Recommended for performance
],
],
Set default to 'singlestoredb' or 'singlestore'.
First Use Case:
Run a migration with SingleStore-specific features (e.g., shardKey):
Schema::create('users', function (Blueprint $table) {
$table->id();
$table->string('email')->unique();
$table->shardKey('email'); // SingleStore-specific
$table->timestamps();
});
Schema::create('high_freq_transactions', function (Blueprint $table) {
$table->rowstore(); // Optimized for OLTP
$table->increments('id');
$table->string('data')->sparse(); // Sparse column
});
Schema::create('analytics', function (Blueprint $table) {
$table->shardKey('user_id'); // Distribute data
$table->sortKey(['event_date', 'desc']); // Optimize queries
});
JSON Columns:
Use json type for nested data:
Schema::create('profiles', function (Blueprint $table) {
$table->json('metadata'); // Native JSON support
});
Access via Eloquent:
$profile->metadata['key'] = 'value';
Global Temporary Tables:
Schema::create('temp_session', function (Blueprint $table) {
$table->temporary()->global(); // Visible across sessions
});
INSERT/UPDATE:
DB::table('users')->insert([
['name' => 'Alice', 'email' => 'alice@example.com'],
['name' => 'Bob', 'email' => 'bob@example.com'],
]);
Schema::create('articles', function (Blueprint $table) {
$table->text('content');
$table->fullText('content'); // FULLTEXT index
});
DB::table('articles')->where('content', 'like', '%laravel%')->get();
config/database.php for high-throughput apps:
'options' => [
PDO::ATTR_PERSISTENT => true,
],
'options' => [
PDO::MYSQL_ATTR_SSL_CA => base_path('singlestore_bundle.pem'),
],
singlestoredb in phpunit.xml:
<env name="DB_CONNECTION" value="singlestoredb"/>
$this->artisan('migrate:fresh')
->expectsQuestion('Proceed with migration?', 'yes')
->assertExitCode(0);
ORDER BY in DELETE/UPDATE:
SingleStore rejects ORDER BY in these queries. Workaround:
// config/database.php
'ignore_order_by_in_deletes' => true,
'ignore_order_by_in_updates' => true,
Note: Results may be non-deterministic with LIMIT/OFFSET.
PHP < 8.1 and PDO::ATTR_EMULATE_PREPARES:
Returns numeric values as strings. Solutions:
protected $casts = [
'user_id' => 'integer',
];
Shard Key Misconfiguration:
uuid).SHOW TABLE STATUS LIKE 'your_table'.Global Temporary Tables:
DB::statement('DROP TEMPORARY TABLE IF EXISTS temp_session');
Query Logging:
Enable in config/database.php:
'logging' => true,
'log' => storage_path('logs/singlestore.log'),
Check logs for malformed queries (e.g., unsupported syntax).
Connection Issues:
openssl s_client -connect your-cluster.singlestore.com:3306 -showcerts
mysql -h your-host -u user -p
Performance Bottlenecks:
SHOW PROCESSLIST for long-running queries.EXPLAIN for complex joins:
DB::select('EXPLAIN SELECT * FROM users JOIN orders ON users.id = orders.user_id');
Custom Table Options:
Extend Blueprint for SingleStore-specific options:
// app/Extensions/SingleStoreBlueprint.php
use Illuminate\Database\Schema\Blueprint;
class SingleStoreBlueprint extends Blueprint {
public function columnstoreSegment($rows) {
$this->columnstoreSegmentRows = $rows;
}
}
Usage:
Schema::create('analytics', function (Blueprint $table) {
$table->sortKey('timestamp')->with(['columnstore_segment_rows' => 100000]);
});
Query Builder Macros: Add SingleStore-specific methods:
DB::macro('shardedQuery', function ($query) {
return $query->toSql() . " /*+ SHARD_KEY(user_id) */";
});
Event Listeners: Hook into migrations for post-creation tasks:
Schema::create('users', function (Blueprint $table) {
$table->shardKey('email');
})->after(function () {
DB::statement('ALTER TABLE users ADD INDEX idx_email (email)');
});
Use reference Tables Sparingly:
Replication overhead grows with data size. Reserve for small lookup tables (e.g., countries).
Leverage sparse Columns:
Reduce storage for rarely used fields (e.g., profile_picture in a users table).
Batch Migrations:
For large tables, use DB::transaction() with chunking:
DB::transaction(function () {
User::chunk(1000, function ($users) {
foreach ($users as $user) {
$user->update(['status' => 'active']);
}
});
});
Monitor Idle Connections:
SingleStore handles ~100K idle connections by default. Adjust max_connections in my.cnf if needed:
[mysqld]
max_connections = 100000
How can I help you explore Laravel packages today?