对于100k记录,MySQL需要10秒才能计算条件

时间:2012-05-31 09:32:29

标签: mysql query-optimization

SELECT COUNT(*) AS count_all, products.id AS products_id 
FROM `products` 
INNER JOIN `product_device_facilities` 
  ON `product_device_facilities`.`product_id` = `products`.`id` 
INNER JOIN `product_vendors` 
  ON `product_vendors`.`ProductId` = `products`.`id` 
INNER JOIN `screen_shots` 
  ON `screen_shots`.`ProductVendorId` = `product_vendors`.`id` 
WHERE ( (DownloadCount >= 10 or DownloadCount is NULL) 
  and (Minsdk <= 10 or Minsdk is null)) 
GROUP BY products.id 
HAVING GROUP_CONCAT(device_facility_id ORDER BY device_facility_id ASC ) IN (0)

对于100k记录,这需要10秒钟。

如何改善表现?

3 个答案:

答案 0 :(得分:4)

您可以尝试一些事项。

  1. 使用与数据库的持久连接以避免连接开销
  2. 检查所有表格是否在密钥表上都有主键,例如(产品)
  3. 每行使用较少的RAM,通过声明列只需要保存存储在其中的值。即@manurajhada表示不使用count(*)使用count(主键)
  4. 发出GRANT语句时使用更简单的权限可以使MySQL减少权限检查开销。
  5. 在不同表之间的引用上使用索引。只记得不要索引过多的列,简单的经验法则,如果你从未在比较中引用过一列,就没有必要对它进行索引。
  6. 尝试使用ANALYZE TABLE帮助mysql更好地优化查询。
  7. 您可以通过确保所有非空的coum声明为NOT NULL来加快查询速度 - 因此您可以加快表格遍历的速度。
  8. 调整MySQL缓存:为缓冲区分配足够的内存(例如SET GLOBAL query_cache_size = 1000000)并根据平均查询结果集大小定义query_cache_min_res_unit
  9. 我知道这听起来很反直,但有时值得对表进行去规范化,即在几个表中复制一些数据以避免昂贵的JOIN。您可以使用外键或触发器来支持数据完整性。
  10. 如果所有其他方法都失败了

    1. 升级您的硬件,如果可以的话,更多的RAM,更快的硬盘可以对数据库的速度产生重大影响,并且当您完成后,为mysql分配更多的内存。
    2. 编辑

      • 如果您不需要结果,另一个选项@ ask-bjorn-hansen建议您每天可以使用一次后台任务(cron作业),并将查询结果存储在单独的表中,然后存储在您的应用程序您需要做的就是检查该表以获取返回的结果,这样您就可以查询100k结果,并且能够运行需要数小时且不会过度影响用户的查询。

答案 1 :(得分:1)

对表上的连接列进行索引而不是使用count(*)使用count(某些索引的主键列)。

答案 2 :(得分:1)

minsdk和下载计数是否在同一个表中?如果是这样的话,在这两者上添加索引可能有所帮助。

这可能是一个很难/不可能的快速查询。如果没有看到完整的架构和数据,那么很难具体,但是将它分成几个更容易执行的查询可能会更快。或者正如Amadeus建议的那样可能会对数据进行非规范化。

另一个变化是只需花费10秒就可以忍受,但要确保它总是在后台定期(使用cron或类似),而不是在用户等待时。然后花时间修复它,如果/需要几分钟而不是几秒钟,否则会给您的用户体验或服务器带来不可接受的负担。