Sql 在200K数据库上查询结果耗时过长,是否加快提示?

Sql 在200K数据库上查询结果耗时过长,是否加快提示?,sql,mysql,postgresql,sqlalchemy,Sql,Mysql,Postgresql,Sqlalchemy,我有一个sql语句,其中连接了大约4个表,每个表有200000行。查询运行,但保持冻结状态。当我对3个表执行连接时,它返回行(大约需要10秒)。有什么建议吗?加速的建议 谢谢 代码 p、 如果有帮助的话,我正在使用sqlalchemy生成这段代码,这段代码的sqlalchemy代码是 query = session.query(equipment, tiremap, workreference, tirework) query = query.filter(equipment.c.tirema

我有一个sql语句,其中连接了大约4个表,每个表有200000行。查询运行,但保持冻结状态。当我对3个表执行连接时,它返回行(大约需要10秒)。有什么建议吗?加速的建议

谢谢

代码

p、

如果有帮助的话,我正在使用sqlalchemy生成这段代码,这段代码的sqlalchemy代码是

query = session.query(equipment, tiremap, workreference, tirework)
query = query.filter(equipment.c.tiremap == tiremap.c.TireID)
query = query.filter(tiremap.c.WorkMap==workreference.c.aMap)
query = query.filter(workreference.c.bMap == tirework.c.workmap)
query = query.limit(5)
query.all()

可能是你要加入的第四张桌子比其他桌子大得多。也可能是您要加入的列上没有索引。

请确保您在以下列上有索引:

  • 设备(tiremap)
  • 提雷马克(提雷德)
  • tiremap(工作图)
  • 工作参考(aMap)
  • 工作参考(bMap)
  • 疲劳作业(工作图)
编辑:为了完整性,我想我应该提供一些上下文

SQL优化器查看语句,对其进行解析,然后根据查询、引用的表和可用索引确定语句的执行计划。如果您执行
从tab1
中选择*的操作,那么它将对tab1执行完整的表扫描,因为没有其他方法可以执行该操作

如果您从lastname(如“V%”)所在的人中选择*,并且您有一百万条记录,则查询每一行的速度会很慢,但如果将lastname编入索引,则效率会高得多

对于像您这样的查询,其中一个表将是驱动表,不管索引如何,都可以作为完整表扫描来完成。这没什么问题。必须有一个表来驱动查询。如果有一个
WHERE
子句(对于连接条件以外的内容),这可能会改变,但在其他情况下通常是正确的

从该驱动表中,MySQL将开始向执行计划添加连接。这些连接需要另一端的索引才能有效地工作

因此,对于三个表,您可能有一个表没有索引,但这并不重要,因为它驱动查询。对于第四个表,可能有两个未索引的表,这现在是一个问题,因为对于一个MySQL中的每一行,都必须对另一行进行完整的表扫描

因此,基本上,您可以在每个外键和联接列上创建一个索引,这样MySQL就可以使用现有的资源为您提供的查询制定最佳的执行计划


最后,大多数工具都会告诉您数据库模式。PHPMyAdmin是托管数据库的常用工具。就我个人而言,我真的很喜欢这种桌面应用。这是一个不错的免费工具。

大多数SQL数据库都有一些“解释计划”或“解释”的变体,您可以使用它们来查看它是如何解析查询的。寻找完整的表扫描作为需要索引的地方。

您正在进行4个表的自然连接。此外,在您的“WHERE”声明中,没有特殊条件

数据库引擎将执行以下操作:

它将首先对每个表中的所有数据进行递归积

考虑表A、B和C中的以下行:

A = rowA1
    rowA2
    rowA3;
B = rowB1
    rowB2
    rowB3;
C = rowC1
    rowC2
    rowC3;
基本上,如果对这3个表进行自然联接,引擎内存中将包含:

rowA1 - rowB1 - rowC1
rowA1 - rowB1 - rowC2
rowA1 - rowB1 - rowC3
rowA1 - rowB2 - rowC1
rowA1 - rowB2 - rowC2
rowA1 - rowB2 - rowC3
rowA1 - rowB3 - rowC1
rowA1 - rowB3 - rowC2
rowA1 - rowB3 - rowC3
...
...
...
rowA3 - rowB3 - rowC1
rowA3 - rowB3 - rowC2
rowA3 - rowB3 - rowC3
总共有27行被放入内存。但是,我们只需要3行:

rowA1 - rowB1 - rowC1
rowA2 - rowB2 - rowC2
rowA3 - rowB3 - rowC3
如果您的数据库引擎不能自行进行优化,那么自然连接3个表的代价是非常昂贵的。对于4个表,这是无法想象的,即使是对于数量有限的行

现在,我们怎样才能得到更好的东西

首先,通过查看代码,我们知道我们只需要5个值。另外,在数据库优化中,据说应该尽可能早地进行选择

下面是一些未经测试的代码,应该可以帮助您。您可能需要修改它,具体取决于您使用的DB引擎:

SELECT *
FROM (SELECT * FROM equipment LIMIT 5) e, tiremap, workreference, tirework
WHERE e.tiremap = tiremap.TireID AND
      tiremap.WorkMap = workreference.`aMap` AND
      workreference.`bMap` = tirework.workmap
只要这样做,我们就会觉得只有3张桌子,而不是4张。不过,这并不是你真正想要的。如果其他表中未引用“设备”的一行,则最后的行数将少于5行。但是,这是一个示例,向您展示了我们可能并不真正需要所有表中的所有行

现在,我想你想要的可能是:

SELECT * FROM equipment 
INNER JOIN tiremap ON equipment.tiremap = tiremap.TireID
INNER JOIN workreference ON tiremap.WorkMap = workreference.aMap
INNER JOIN tirework ON workreference.bMap = tirework.workmap
LIMIT 5
您可能会遇到一个问题:如果您的引擎不是很好(mySQL,对不起),那么可能需要很长时间

如果您真的想自己进行优化:

SELECT * FROM tirework, 
   (SELECT * FROM workreference, 
       (SELECT * FROM tiremap,
           (SELECT * FROM equipment) e
        WHERE e.tiremap = tiremap.TireID) t
    WHERE t.WorkMap = workreference.aMap) w
WHERE w.bMap = tirework.workmap
LIMIT 5
瞧!即使您的引擎优化器不存在,该查询也不会花费太长时间。您的引擎将一次只做一个产品,并在将其与新表连接之前将坏行清除,而不是将所有内容都制作成一个大产品


试试看。

是否总是排除同一张表以使其正常工作?换句话说,您能让它与4个可能的表中的任意3个一起工作吗?或者是一个特定的表一直是问题所在?您是否已将此解释运行一遍,以了解它在做什么?这应该是您的第一步。@MusiGenesis,我能够以相当快的速度运行前3个表的sql,但一旦我开始加入到繁重的工作中,它似乎冻结了,并且没有响应,您认为问题出在哪里?还有,有没有办法知道这些表是否被索引?好的,nvm,我只是用谷歌搜索了一下。谢谢。@colorfulgrayscale为我的声明添加了一些上下文。zomg,非常感谢。这正是我想要的。和平。
SELECT * FROM tirework, 
   (SELECT * FROM workreference, 
       (SELECT * FROM tiremap,
           (SELECT * FROM equipment) e
        WHERE e.tiremap = tiremap.TireID) t
    WHERE t.WorkMap = workreference.aMap) w
WHERE w.bMap = tirework.workmap
LIMIT 5