SELECT
`id`, `code`, `description`, `minamt`
FROM `coupons`
WHERE
`starts`<=DATE_FORMAT(NOW(),"%Y-%m-%d")
AND
`ends`>=DATE_FORMAT(NOW(),"%Y-%m-%d")
and
active=1
and
is_public=1
此mysql执行过程需要6到7秒,因为优惠券表中有10万条记录
表结构
CREATE TABLE IF NOT EXISTS `coupons` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`bulk_coupon` int(11) DEFAULT '0',
`ctype` tinyint(1) NOT NULL DEFAULT '1' COMMENT 'Type',
`code` varchar(255) COLLATE utf8_bin NOT NULL DEFAULT 'n/a' COMMENT 'Code',
`discount` float(10,2) NOT NULL DEFAULT '0.00' COMMENT 'Discount',
`description` text COLLATE utf8_bin,
`minamt` float(10,2) NOT NULL DEFAULT '0.00' COMMENT 'Min. amount',
`custlogin` tinyint(1) NOT NULL DEFAULT '2' COMMENT 'Requires customer login',
`freeshipping` tinyint(1) NOT NULL DEFAULT '2' COMMENT 'Free shipping',
`customer` text COLLATE utf8_bin,
`products` text COLLATE utf8_bin COMMENT 'Specific products',
`categories` text COLLATE utf8_bin COMMENT 'Spedific categories',
`aod` tinyint(1) NOT NULL DEFAULT '1' COMMENT 'Apply on discounted products',
`starts` date NOT NULL COMMENT 'Start on',
`ends` date NOT NULL COMMENT 'Ends on',
`is_public` tinyint(1) DEFAULT '0',
`active` tinyint(1) DEFAULT '2' COMMENT 'Active',
`usage_type` tinyint(1) DEFAULT '0',
`is_used` tinyint(1) DEFAULT '0',
`cod_applicable` tinyint(1) DEFAULT '0',
`return_policy` tinyint(1) DEFAULT '1',
`added` datetime DEFAULT NULL,
`modified` datetime DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `startEndDate` (`starts`,`ends`,`is_public`,`active`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin AUTO_INCREMENT=1201682 ;
答案 0 :(得分:1)
简化:
+------------+-------------------------------+
| CURDATE() | DATE_FORMAT(NOW(),"%Y-%m-%d") |
+------------+-------------------------------+
| 2019-02-19 | 2019-02-19 |
+------------+-------------------------------+
需要索引(Optimizer将选择其中一个):
INDEX(active, is_public, start)
INDEX(active, is_public, end)
请勿使用FLOAT
或DOUBLE
作为货币。使用DECIMAL
。
答案 1 :(得分:0)
查询重写可能是
查询
SELECT
coupons.id
, coupons.code
, coupons.description
, coupons.minamt
FROM (
SELECT
coupons.id
FROM coupons
WHERE
coupons.starts <= DATE_FORMAT(NOW(),"%Y-%m-%d")
and
coupons.active=1
and
coupons.is_public=1
) AS coupons_start
INNER JOIN
coupons
ON
coupons_start.id = coupons.id
AND
coupons.starts <= DATE_FORMAT(NOW(),"%Y-%m-%d")
AND
coupons.ends >= DATE_FORMAT(NOW(),"%Y-%m-%d")
这个接缝有一个查询“更好”的执行计划。
请记住,在空表上执行计划并不是很合理。
因此,您还需要在自己的MySQL上进行解释
EXPLAIN
SELECT
`id`, `code`, `description`, `minamt`
FROM `coupons`
WHERE
`starts`<=DATE_FORMAT(NOW(),"%Y-%m-%d")
AND
`ends`>=DATE_FORMAT(NOW(),"%Y-%m-%d")
and
active=1
and
is_public=1
;
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
| --- | ----------- | ------- | ----- | ------------- | ------------ | ------- | --- | ---- | ----------- |
| 1 | SIMPLE | coupons | range | startEndDate | startEndDate | 3 | | 1 | Using where |
请注意,key_len
只有3,这意味着查询只能使用startEndDate
键的一小部分
EXPLAIN
SELECT
coupons.id
, coupons.code
, coupons.description
, coupons.minamt
FROM (
SELECT
coupons.id
FROM coupons
WHERE
coupons.starts <= DATE_FORMAT(NOW(),"%Y-%m-%d")
) AS coupons_start
INNER JOIN
coupons
ON
coupons_start.id = coupons.id
AND
coupons.starts <= DATE_FORMAT(NOW(),"%Y-%m-%d")
AND
coupons.ends >= DATE_FORMAT(NOW(),"%Y-%m-%d")
AND
coupons.active = 1
AND
coupons.is_public = 1
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
| --- | ----------- | ------- | ----- | ------------- | ------------ | ------- | --- | ---- | --------------------------------------------------- |
| 1 | PRIMARY | | | | | | | | Impossible WHERE noticed after reading const tables |
| 2 | DERIVED | coupons | index | startEndDate | startEndDate | 10 | | 1 | Using where; Using index |
就像我真的说的那样,在空表上进行解释并不是很听起来。
请注意Impossible WHERE noticed after reading const tables
优化器,这里的表为空。
但还要注意,key_len
为10,具有索引类型并使用索引,这意味着内部查询可以单独从索引文件中获取ID所要加入的信息。