【问题标题】:Mysql Query takes too much time to executeMysql Query 执行时间过长
【发布时间】:2014-03-20 14:40:19
【问题描述】:

所以我需要表格,products_used aprox 600MB 和 products_language_description 大约 5MB,但问题是这个查询永远不会完成运行......

我已经尝试修复,优化分析,我不知道如何改进这个......

SELECT pu.products_id, count(pu.products_id) as products_count, p.products_name,
pu.time_used FROM products_used pu, products_language_description p
WHERE pu.merchant_id='69'
AND p.products_id=pu.products_id GROUP BY products_id ORDER BY products_count
DESC LIMIT 0, 20



CREATE TABLE `products_used` (
    `products_used_id` INT(15) NOT NULL AUTO_INCREMENT,
    `plans_key` VARCHAR(255) NOT NULL DEFAULT '0',
    `products_id` BIGINT(20) NOT NULL DEFAULT '0',
    `customers_id` INT(10) NOT NULL DEFAULT '0',
    `merchant_id` INT(10) NOT NULL DEFAULT '0',
    `time_used` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00',
    PRIMARY KEY (`products_used_id`),
    INDEX `plans_key` (`plans_key`)
)
COLLATE='latin1_swedish_ci'
ENGINE=MyISAM
AUTO_INCREMENT=24625441;

CREATE TABLE `products_language_description` (
    `products_id` INT(5) NOT NULL DEFAULT '0',
    `products_description` LONGTEXT NOT NULL,
    `products_name` TEXT NOT NULL COLLATE 'utf8_general_ci',
    `products_help_info` LONGBLOB NOT NULL,
    `products_language` VARCHAR(255) NOT NULL DEFAULT '',
    PRIMARY KEY (`products_id`, `products_language`)
)
COLLATE='latin1_swedish_ci'
ENGINE=MyISAM;

【问题讨论】:

  • 那么您是否尝试过对您的查询进行解释,或者考虑在表上放置适当的索引? (例如,products_used.product_id 上的索引,或者products_used.merchant_id 上的索引
  • 将索引放在要使用 WHERE 子句的任何字段上通常是一个很好的经验法则,尤其是当该字段中存在重复值时。
  • 我强烈建议使用显式而不是隐式连接

标签: php mysql sql performance


【解决方案1】:

尝试将索引添加到products_used 表上的product_idmerchant_id 字段

【讨论】:

    【解决方案2】:

    看看你的 WHERE 部分。

    在哪里 pu.merchant_id='69' AND p.products_id=pu.products_id GROUP BY products_id

    您正在比较两种不同的数据类型:

    • products_id INT(5) NOT NULL DEFAULT '0',
    • products_id BIGINT(20) NOT NULL DEFAULT '0',

    另外,您以不必要的方式使用单引号:

    • pu.merchant_id='69'

    也许您需要在第一种情况下创建一些索引。外键也有帮助!

    也许这对你有帮助!

    【讨论】:

      【解决方案3】:

      对于这个查询:

      SELECT pu.products_id, count(pu.products_id) as products_count,
             p.products_name, pu.time_used
      FROM products_used pu join
           products_language_description p
           on p.products_id = pu.products_id
      WHERE pu.merchant_id = '69'
      GROUP BY pu.products_id
      ORDER BY products_count DESC
      LIMIT 0, 20
      

      您希望在products_used(merchant_id, products_id) 上建立索引。在 MySQL 中,有时您可以使用相关子查询重写聚合查询以改善结果:

      SELECT pu.products_id,
             (select count(*)
              from products_language_description p
              where p.products_id = pu.products_id
             ) as products_count,
             p.products_name, pu.time_used
      FROM products_used pu
      WHERE pu.merchant_id = '69'
      ORDER BY products_count DESC
      LIMIT 0, 20;
      

      这会将外部group by 替换为相关查询中应该只使用主键索引的聚合。

      编辑:

      等等。你的问题是这两个定义:

      CREATE TABLE `products_used` (
          . . . 
          `products_id` BIGINT(20) NOT NULL DEFAULT '0',
      )
         . . .
      CREATE TABLE `products_language_description` (
          `products_id` INT(5) NOT NULL DEFAULT '0',
           . . . 
      )
      

      连接条件使用不同的数据类型。修复表结构,使列具有相同的类型(使用alter table . . .)或重建它们。

      【讨论】:

      • 我已经添加了索引,现在正在使用旧查询运行,但它显示,但速度很慢,所以现在关于您的查询我收到一个错误:SQL Error (1064): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'p) as products_count, p.products_name, pu.time_used FROM products_used pu WHERE' at line 1
      • 我的 products_id INT(5) 还是一样的问题
      【解决方案4】:

      正如 Gordon 所提到的,我会将您的产品使用表上的索引扩展为 (merchant_id, product_id, time_used ),因此它是一个覆盖索引,并且不必转到原始数据来获取您的 count()。现在,对于给定的商家,您在 products_used 表中有多个相同的“products_id”实例对我来说似乎很奇怪,但这是另一回事。

      我会针对您想要的商家对产品 ID、计数和时间进行内部预查询。否则,就像在 Gordon 的查询示例中一样,我会先预查询每个产品,然后再为商家获取这些产品。

      我建议预先查询特定于商家使用的内部产品,然后在返回 THAT 后,获取产品名称。

      SELECT 
            JustByMerchant.products_id, 
            JustByMerchant.products_count, 
            p.products_name,
            JustByMerchant.time_used 
         FROM
            ( select 
                    pu.products_id, 
                    count(*) as products_count, 
                    pu.time_used 
                 from
                    products_used pu
                 where
                    pu.merchant_id = 69
                 group by 
                    pu.products_id
                 order by
                    COUNT(*) DESC
                 limit 
                    0, 20 ) JustByMerchant
              JOIN products_language_description p
                 ON JustByMerchant.products_id = p.products_id
      

      【讨论】:

        猜你喜欢
        • 2018-01-19
        • 2023-03-16
        • 1970-01-01
        • 1970-01-01
        • 2012-03-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多