查询花了太多时间加载

时间:2014-01-25 17:52:40

标签: mysql sql

 ( SELECT 'no' AS aff,
         ss.orderid, ss.secondaff, ss.saletype, ss.price,
         ss.affiliate, ss.vendor,
         ss.cpa,ss.rebill,ss.salests,ss.fname,ss.lname 
    FROM sales ss 
   WHERE 1=1
     AND ( ss.vendor='3kpertrade' OR ss.affiliate='3kpertrade') 
ORDER BY ss.salests DESC ) 
  UNION ALL 
 (   SELECT 'yes' AS aff, ss.orderid,ss.secondaff,ss.saletype,sf.price,
            ss.affiliate,ss.vendor,ss.cpa,ss.rebill,ss.salests,ss.fname,ss.lname 
       FROM salesaff sf 
      INNER JOIN sales ss ON ss.orderid=sf.orderid 
      WHERE 1=1 
        AND ( ss.vendor='3kpertrade' OR ss.affiliate='3kpertrade') 
   ORDER BY sf.salests DESC ) 
ORDER BY salests DESC

我需要从具有给定条件的sales表中选择数据,如果vendor = affiliate在sales表中,并且ss.orderid = sf = orderid,则需要从salesaff表中选择数据。

我写了一些帮助,但查询花了195秒加载。 sales table包含8000行和销售商,供应商,附属机构,orderid索引。 salesaff表包含6000行,并由orderid索引

两个表都包含相同的列。

一些事实: - >如果我从两者中删除自定义列('yes'作为aff,'no'作为aff),那么如果我使用limit 100或者其他东西,则执行查询。否则加载需要195秒。

如果我使用限制100,则在2秒内执行查询。但是没有限制,它给出了错误代码500。 而且,我也需要总价。有人能帮助我吗?

3 个答案:

答案 0 :(得分:1)

第一个效率是子查询中的order by不是必需的,除非你在那里放置限制条款。所以试试这个:

(SELECT 'no' AS aff, ss.orderid, ss.secondaff, ss.saletype, ss.price, ss.affiliate, 
         ss.vendor, ss. cpa, ss.rebill, ss.salests, ss.fname, ss.lname 
 FROM sales ss 
 WHERE 1=1 AND ( ss.vendor='3kpertrade' OR ss.affiliate='3kpertrade')
) 
UNION ALL 
( SELECT 'yes' AS aff, ss.orderid, ss.secondaff, ss.saletype, sf.price, ss.affiliate, 
         ss.vendor, ss.cpa, ss.rebill, ss.salests, ss.fname, ss.lname 
 FROM salesaff sf INNER JOIN
      sales ss
      ON ss.orderid = sf.orderid 
 WHERE 1=1 AND ( ss.vendor='3kpertrade' OR ss.affiliate='3kpertrade') 
 ) 
ORDER BY salests DESC

答案 1 :(得分:1)

嘿嘿嘿。这很难。您可能获得了正确的结果,但您的托管服务提供商正在超时您的查询,因此您无法分辨。这两个表对我来说似乎不是很大。

首先,如果可以,请增加超时时间,尤其是调试时。如果你的低效查询没有完成,很难确保正确性。如果它错了,那么世界上最有效的查询就毫无价值。请向您的托管服务提供商支持人员寻求帮助。

其次,如果查询完成并返回结果集的第一行需要很长时间,您将获得超时。如果您的宿主语言使用整个结果集的速度很慢,您也可能会超时,因此请确保您有效地执行此操作。

第三,让我们把它分解。您正在查找特定的销售记录集。你正在进行OR操作。最有可能保证全表扫描,这对性能不太好。

您也可以跳过1=1条款中的WHERE。这通常被放在那里作为一个hack,使宿主语言的代码构造更简单一些。它不应该损害性能,但它无济于事。

进行一些猜测:假设ss.orderid是唯一(自动增量)主键字段,您可以尝试添加复合索引 - 覆盖索引 -

   (vendor, orderid)

   (affiliate,orderid) 

然后使用以下查询来检索您需要查找的orderid值列表。

         SELECT orderid FROM sales WHERE vendor = '3kpertrade'
          UNION
         SELECT orderid FROM sales WHERE affiliate = '3kpertrade'

此子查询有效地查找您需要的orderid值集。我建议的两个覆盖索引将显着提高性能。 (请勿在此处使用UNION ALL,使用UNION,否则您可能会获得一些重复数据。)

然后,您可以使用此查询获取部分订单数据 - UNION ALL的第一部分。

SELECT 'no' AS aff,
       ss.orderid, ss.secondaff, ss.saletype, ss.price,
       ss.affiliate, ss.vendor,
       ss.cpa,ss.rebill,ss.salests,ss.fname,ss.lname 
  FROM sales ss 
  JOIN (
         SELECT orderid FROM sales WHERE vendor = '3kpertrade'
          UNION
         SELECT orderid FROM sales WHERE affiliate = '3kpertrade'
       ) ids ON ss.orderid = ids.orderid 

我建议您使用这么多查询来调试您的应用。确保它显示正确的内容。

您似乎在查询中实施了影子预订系统。也就是说,当您的salesaff表格中出现特定订单时,您在此查询的结果集中重复它。看起来您从salesaff检索的唯一信息就是价格。那是对的吗?会员销售是否会在UNION ALL结果集中多次显示?

沿着这些相同的行,查询的后半部分将如下所示:

SELECT 'yes' AS aff, ss.orderid, ss.secondaff, ss.saletype,
        sf.price,
        ss.affiliate, ss.vendor, ss.cpa, ss.rebill, ss.salests, ss.fname, ss.lname 
  FROM sales AS ss 
  JOIN (
         SELECT orderid FROM sales WHERE vendor = '3kpertrade'
          UNION
         SELECT orderid FROM sales WHERE affiliate = '3kpertrade'
       ) ids ON ss.orderid = ids.orderid 
  JOIN salesaff sf ON ss.orderid=sf.orderid 

如果您从salesaff提取的唯一信息实际上是价格,那么覆盖索引

 (orderid, price)

将有助于此查询。

最后,执行UNION ALL和ORDER BY

观察。如果sales.salests是时间戳,并且sales.orderid是自动递增索引,并且您永远不会更新sales.salests但只插入它,那么ORDER BY orderid DESC将执行相同的操作为ORDER BY salests DESC。这可能会节省一点时间。

答案 2 :(得分:0)

您可以通过一次遍历表并对salesaff表进行左连接来完全简化。然后情况/何时为您的是/否状态

我会有一个索引(供应商,aaffiliate,salests)

SELECT 
      CASE when sf.orderid is null 
           then 'no' else 'yes' end AS aff,
      ss.orderid, 
      ss.secondaff, 
      ss.saletype, 
      ss.price,
      ss.affiliate, 
      ss.vendor,
      ss.cpa,
      ss.rebill,
      ss.salests,
      ss.fname,
      ss.lname 
   FROM 
      sales ss
         LEFT JOIN salesaff sf 
            ON ss.orderid=sf.orderid 
   WHERE
         ss.vendor = '3kpertrade' 
      OR ss.affiliate = '3kpertrade'
   ORDER BY 
      ss.salests DESC