在大表缓慢的SQL,按时间戳过滤(int12)

问题描述:

我有一个缓慢的查询问题,使一个“简单”选择..我不明白是什么问题...这是一个大桌子..但这是一个简单的查询..在大表缓慢的SQL,按时间戳过滤(int12)

的表格:

business: (1.000.000 reg) 
id (INDEX PRIMARY INT(11) UNSIGNED) 
active (INDEX TINYINT(1)) 

products: (32.000.000 reg) 
id (INDEX PRIMARY INT(11) UNSIGNED) 
business_id (INDEX INT(11) UNSIGNED) 
offer_start (INDEX INT(12) UNSIGNED) (timestam unix) 
offer_end (INDEX INT(12) UNSIGNED) (timestamp unix) 
price_offer (VARCHAR(10)) (price with decimals) 
active (INDEX TINYINT(1)) 

business.id,products.id,products.offer_start和products.offer_end被INDEX(分离)

当我做这个:

SELECT SQL_NO_CACHE * FROM products 
LEFT JOIN business ON business.id = products.business_id 
WHERE 
(business.active = '1' AND business.paylimit > 1314029906) 
AND 
(products.active = '1' AND products.offer_start < 1314029906 AND products.offer_end > 1314029906 AND products.price_offer > 0) 
LIMIT 0,10 

拿21秒。 问题是这样的:products.offer_start < 1314029906 AND products.offer_end > 1314029906需要约20秒才能给我结果

是否可以使这个查询过滤其他表单来加速?

+1

你能提供的解释计划? –

+0

你也很可能得到错误的答案。 WHERE(business.active ='1'AND business.paylimit> 1314029906)会将左连接更改为内连接,因为它必须符合该条件。 – HLGEM

+0

什么是offer_start和offer_end的确切索引?他们是两个单独的索引吗?该索引是否包含任何其他列? –

餐桌架构的一些注意事项:

  1. offer_start(INDEX INT(12)UNSIGNED) - 12没有任何意义,因为INT最大的符号是11同为OFFER_END
  2. 活跃(INDEX TINYINT(1)) - 索引是无用的,因为1000000上的基数将是2 - 1或0
  3. price_offer(VARCHAR(10)) - 您可以使用浮点数或小数点。 products.price_offer> 0将工作得更快。
+2

从不使用浮点值进行价格计算,小数点是这里的正确类型 – Crack

尝试

SELECT SQL_NO_CACHE * FROM products 
    LEFT JOIN business ON business.id = products.business_id 
WHERE business.paylimit > 1314029906 
    AND products.offer_start < 1314029906 
    AND products.offer_end > 1314029906 
    AND products.price_offer > 0 
    AND business.active = '1' 
LIMIT 0,10 

的MySQL从左至右处理过滤器右侧所以要确保这是最选择性(返回最少行)的条件是在左边。在条件的最左侧有business.active = '1'可以使用索引,但如果它的选择性为50%,则该条件的其他部分并没有使用索引。

您可能要阅读手册中的How MySQL Uses Indexes

编辑: 关于MySQL如何使用索引的简短解释:3 ways MySQL uses indexes