dimanche 29 septembre 2019

Active record lookup - find_by_inventory_product_id is intermittently slow inspite of adding index

I have a simple new API endpoint, which involves querying my newly setup and populated table - inventory_products.

The schema of inventory_products table is :

CREATE TABLE `inventory_products` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `inventory_product_id` binary(16) DEFAULT NULL,
  `product_id` binary(16) DEFAULT NULL,
  `status` enum('ACTIVE','INACTIVE','DELETED') DEFAULT 'ACTIVE',
  `priority` int(11) DEFAULT '0',
  `inventory_service_id` tinyint(3) DEFAULT NULL,
  `created_at` datetime DEFAULT NULL,
  `updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
  UNIQUE KEY `uc_inventory_product_id` (`inventory_product_id`),
  KEY `idx_product_status` (`product_id`,`status`)
) ENGINE=InnoDB AUTO_INCREMENT=76312817 DEFAULT CHARSET=utf8;

The API endpoint mainly does the below:

def lookup_inventory_service_id
    return render_error_response(AUTH_ERROR, {status: 403}) unless client.name == PERMITTED_NAME

    ip_fetch_start = Time.now
    inventory_product = InventoryProducts.find_by_inventory_product_id(resource_attributes[:inventory_product_id])
    Rails.logger.info({inventory_product_id: resource_attributes[:inventory_product_id], inventory_product_fetch_time_ms: (Time.now - ip_fetch_start)*1000}.as_json)
    return head :not_found unless inventory_product
....

Problem: The inventory_product lookup (find_by_inventory_product_id) is the standard function provided by Rails's ActiveRecord (I have not overwritten it in my model). This function takes from 10ms to sometimes even 650ms (found this from the logs I added). Why would this take up so much time in some cases and so less time in some other in spite of Mysql index existing on the column used in the lookup?

I have mentioned inventory_product_id as a unique key in my schema and the MySQL query triggered by the above function is using inventory_product_id as an index from the below explain statement.

explain SELECT inventory_products.* FROM inventory_products WHERE inventory_products.inventory_product_id = 0x3a288cdce78d44618eadd72e240f26a4 LIMIT 1

id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE inventory_products const uc_inventory_product_id uc_inventory_product_id 17 const 1 NULL

Is there something wrong in my schema? Do I explicitly need to mention inventory_product_id as a mysql index in the schema? Something like:

KEY `idx_product_status` (`product_id`,`status`)

Thanks, in advance!!

I use Mysql 5.6 and rails - 3.2.8. Also, my rails application runs on a tomcat server (version - Apache Tomcat/7.0.16) inside jruby (1.7.0)/

Aucun commentaire:

Enregistrer un commentaire