在大表缓慢的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秒才能给我结果
是否可以使这个查询过滤其他表单来加速?
答
餐桌架构的一些注意事项:
- offer_start(INDEX INT(12)UNSIGNED) - 12没有任何意义,因为INT最大的符号是11同为OFFER_END
- 活跃(INDEX TINYINT(1)) - 索引是无用的,因为1000000上的基数将是2 - 1或0
- 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
你能提供的解释计划? –
你也很可能得到错误的答案。 WHERE(business.active ='1'AND business.paylimit> 1314029906)会将左连接更改为内连接,因为它必须符合该条件。 – HLGEM
什么是offer_start和offer_end的确切索引?他们是两个单独的索引吗?该索引是否包含任何其他列? –