Tuesday 4 September 2018

Optimize the Mysql query with a Boolean value

I have this table:

CREATE TABLE IF NOT EXISTS `products` (
  `product_id` int(11) NOT NULL AUTO_INCREMENT,
  `supplier_id` int(11) NOT NULL,
  `allowed` varchar(256) NOT NULL,
  `blocked` varchar(256) NOT NULL,
  `approved` tinyint(1) NOT NULL DEFAULT '0',
  PRIMARY KEY (`product_id`),
  KEY `supplier_id` (`supplier_id`),
) ENGINE=InnoDB  DEFAULT CHARSET=utf8;

'approved' is a boolean 0/1 field
'blocked' and 'allowed' hold country codes such as "US CA FR"
I run this query:
SELECT DISTINCT supplier_id
FROM products
WHERE (
    supplier_id=0 OR
    supplier_id = 1207077 OR
    supplier_id = 1207087 OR
    supplier_id = 1207079 OR
    supplier_id = 1207082 OR
    supplier_id = 1207083 OR
    supplier_id = 1207086 OR
    supplier_id = 1207084 OR
    supplier_id = 1207078 OR
    supplier_id = 1207085 OR
    supplier_id = 1207094 OR
    supplier_id = 1207097 OR
    supplier_id = 1207095 OR
    supplier_id = 1207089 OR
    supplier_id = 1207091
) AND (
    (`blocked` NOT LIKE '%US%' AND `allowed` ='') OR
    `allowed` LIKE '%US%'
) AND approved=1;

It runs in about 0.02s. Any suggestions on how to optimize it? Thank you.

The execution speed is the same because OR and non left anchored LIKE clauses cannot use indexes appropriately. You've got bad table design in that US FR etc field, that should be in another table that you join against. If you are stuck with your design and the table is vey large, then create a derived table for the supplier_id OR clauses and then JOIN against the same table in order to find the rest of the matches. This may also require a UNION since you have other OR's. For more information:
http://dev.mysql.com/doc/refman/5.6/en/index-btree-hash.html

0 comments:

Post a Comment