0

I want to improve the performance of my query that's responsible for fetching a stock product from a table. Extremely simple query:

select 
    * -- (I know I should not use "*")
from 
    sync_stock_products 
where 
    slug = 'cable-usb-31-type-c-to-a-male-to-male' and 
    dead = 0 and 
    sync_active = 1 
limit 
    1

There cannot be a more trivial query, right? Now each time I fetch a record, I use its unique slug and two boolean flags (3 where conditions). The Product cannot be dead and must be active. I think it's not relevant what above conditions mean.

enter image description here

Currently, the migration looks like:

public function up()
{
    Schema::create('sync_stock_products', function (Blueprint $table) {
        $table->uuid(SyncInterface::SYNC_MODEL_PRIMARY_KEY_COLUMN_NAME);
        $table->string('stockcode');
        $table->string('slug');
        $table->boolean('dead');
        $table->boolean('stkind1');
        (...) heaps of other columns, removed for shorter snippet
        $table->text('field1')->nullable();
        $table->text('smalpic')->nullable();
        $table->text('highrespic')->nullable();
        $table->text('picture4')->nullable();
        $table->text('picture5')->nullable();
        $table->boolean('nonreturn');
        $table->boolean('sync_flag');
        $table->boolean('sync_active');
        $table->timestamp('created_at')->default(DB::raw('CURRENT_TIMESTAMP'));
        $table->timestamp('updated_at')->default(DB::raw('CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP'));

        // Indexes
        $table->primary(SyncInterface::SYNC_MODEL_PRIMARY_KEY_COLUMN_NAME);
        $table->unique(SyncInterface::COMPOSITE_KEYS['sync_stock_products']);  
    });
}

I already have a primary index on uuid (but I don't use uuid in the query above). I also define unique index on some columns to guarantee composite uniqueness, but this is also irrelevant.

My question is that I want to cover all three columns with index.

Should I put each column in a separate index like:

$table->index('slug');
$table->index('dead');
$table->index('sync_active');

Or:

$table->index(['slug', 'dead', 'sync_active']);

enter image description here

I assume both examples aren't the same? Could someone explain which way is better and would suit this particular case?

Matt Komarnicki
  • 5,198
  • 7
  • 40
  • 92
  • If the `slug` is unique I'd recommend putting a unique index on slug and leaving the other 2 unindexed. Indexing causes inserts/updates to be slower and indexing booleans in case where you also search by an indexed unique column shouldn't add any notable performance – DevK Jan 14 '19 at 03:21
  • [Here](https://stackoverflow.com/questions/179085/multiple-indexes-vs-multi-column-indexes) is a pretty good answer – DevK Jan 14 '19 at 03:22

1 Answers1

0

There is no need to index is_active or dead. The cardinality of these columns is very low and it won't help the DB.

Some DB engines allow to include a column in an index which can ave you an extra read but I don't believe MySQL supports that.

You definitely want to index slug if you are querying for it.

Michal Rogozinski
  • 1,713
  • 1
  • 17
  • 23