Mysql Query需要花费太多时间来执行

时间:2014-03-20 14:40:20

标签: php mysql sql performance

所以我必须使用表products_used aprox 600MB和products_language_description,大约5MB,但问题是这个查询永远不会运行...

我已经尝试过REPAIR,OPTIMIZE ANALYZE,我没有想法如何改善这个......

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;

4 个答案:

答案 0 :(得分:2)

尝试将索引添加到product_id& merchant_id

上的products_used个字段

答案 1 :(得分:0)

对于此查询:

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 . . .)或重建它们。

答案 2 :(得分:0)

看看你的WHERE部分。

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'

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

也许这可以帮到你!

答案 3 :(得分:0)

正如戈登提到的,我会将您的产品使用表的索引扩展到(merchant_id,product_id,time_used),因此它是一个覆盖索引,而不必转到原始数据来获取您的计数()。现在,对于给定商家的products_used表中有多个SAME“products_id”实例,我觉得很奇怪,但这是另一回事。

我会对您想要的商品进行产品ID,计数和时间的内部预先查询。否则,就像在Gordon的查询示例中一样,我首先将每个产品预先伪装,然后在那之外为商家提供这些产品。

我建议预先查询商家特有的内部产品,然后一旦返回,请获取产品名称。

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