1
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 秒。

如何提高性能?

4

3 回答 3

4

您可以尝试一些事情。

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

如果一切都失败了

  1. 如果可以的话,升级你的硬件,更多的内存,更快的硬盘驱动器可以对数据库的速度产生重大影响,当你完成后,为 mysql 分配更多的内存。

编辑

  • 如果您不需要像@ask-bjorn-hansen 建议的那样实时显示结果的另一种选择,您可以每天使用一次后台任务(cron 作业),并将查询结果存储在单独的表中,然后在您的应用程序中必须做的是检查该表的返回结果,这样您就不必查询 100k 结果,并且能够运行需要数小时且不会过度影响您的用户的查询。
于 2012-05-31T10:13:03.153 回答
1

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

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

另一种变化是只需要 10 秒,但要确保它总是在后台定期完成(使用 cron 或类似的),并且永远不要在用户等待时完成。如果/当它需要几分钟而不是几秒钟或以其他方式给您的用户体验或服务器带来不可接受的负担时,请花时间修复它。

于 2012-05-31T10:20:05.610 回答
1

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

于 2012-05-31T09:44:16.250 回答