MySQL查询需要更多时间来获取数据[MySQL]

时间:2018-10-17 11:24:21

标签: mysql sql performance mysql-workbench query-performance

我的500000中有MySQL server个记录表。运行查询时,查询将花费更多时间。有时会超过一分钟。

下面,我添加了我的MySQL机器详细信息。

  

RAM-16GB

     

处理器:Intel®Core™i5-4460M CPU @ 3.20GHz

     

操作系统:Windows服务器64位

我知道我的机器没有问题,因为它是一台独立的机器,并且那里没有其他应用程序。

也许我的查询有问题。我浏览了MySql网站,发现我使用了正确的语法。但是我不确切知道延迟结果的原因。

SELECT SUM(`samplesalesdata50000`.`UnitPrice`) AS `UnitPrice`, `samplesalesdata50000`.`SalesChannel` AS `Channel`
FROM `samplesalesdata50000` AS `samplesalesdata50000`
GROUP BY `samplesalesdata50000`.`SalesChannel`
ORDER BY 2 ASC
LIMIT 200  OFFSET 0

任何人都可以让我知道持续时间是否取决于我使用的表还是查询

  

注意:即使尝试使用索引,结果时间也没有太大差异。

谢谢

4 个答案:

答案 0 :(得分:2)

两种方法:

一种方法是在满足查询所需的列上创建a covering index。您查询的正确索引按以下顺序包含这些列:(SalesChannel, UnitPrice)

为什么有帮助?一方面,索引本身包含满足查询所需的所有数据,而没有别的。这意味着您的服务器工作量更少。

另一方面,MySQL的索引是BTREE组织的。这意味着它们可以按顺序访问。因此您的查询可以一次满足一个SalesChannel,并且MySQL不需要内部临时表。这样更快。

第二种方法涉及到认识到ORDER BY ... LIMIT是一个臭名昭著的性能反模式。您需要MySQL对大量数据进行排序,然后丢弃其中的大部分数据。

您可以尝试以下方法:

SELECT SUM(UnitPrice) UnitPrice,
       SalesChannel Channel
  FROM samplesalesdata50000
 WHERE SalesChannel IN (
         SELECT SalesChannel 
           FROM samplesalesdata50000
          ORDER BY Channel LIMIT 200 OFFSET 0
       )
 GROUP BY SalesChannel 
 ORDER BY SalesChannel 
 LIMIT 200 OFFSET 0

如果您在SalesChannel上有一个索引(上面提到的覆盖索引有效),这应该可以大大提高您的速度,因为您的汇总(GROUP BY)查询只需要考虑表的一个子集。

答案 1 :(得分:0)

您的“ ORDER BY 2 ASC”问题。试试这个“按频道订购”。

答案 2 :(得分:0)

如果是MS SQL Server,则可以使用WITH (NOLOCK)

与MYSQL等效的是

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED ;
SELECT SUM(`samplesalesdata50000`.`UnitPrice`) AS `UnitPrice`, `samplesalesdata50000`.`SalesChannel` AS `Channel`
FROM `samplesalesdata50000` AS `samplesalesdata50000`
GROUP BY `samplesalesdata50000`.`SalesChannel`
ORDER BY SalesChannel  ASC
LIMIT 200  OFFSET 0
COMMIT ;

答案 3 :(得分:0)

要改善OJones的答案,请注意

df1 <- read.table(unz(temp, "Products.txt"), sep="\t", quote = "\"", fill = TRUE, 
                  comment.char = "", header= TRUE) 
df2 <- read.delim(unz(temp, "Products.txt"), sep="\t", header= TRUE) 

all.equal(df1, df2)
# [1] TRUE

identical(df1, df2)
# [1] TRUE

将迅速(假定给定索引)找到所需列表的末尾。然后添加此选项将主查询限制为仅需要的行:

SELECT SalesChannel FROM samplesalesdata50000
    ORDER BY SalesChannel LIMIT 200, 1

但是,这是一个问题。如果表中的行数少于200,则子查询将不返回任何内容。

您似乎要设置“分页”?在这种情况下,可以使用类似的技术来查找起始值:

WHERE SalesChannel < (that-select)

这也避免了使用效率低下的WHERE SalesChannel >= ... AND SalesChannel < ... ,后者必须先读取然后折腾所有跳过的行。 More

但是真正的解决方案可能是建立和维护数据汇总表。它将包含每个月的小计。然后针对“摘要”表运行查询-可能会快10倍。 More