繁体   English   中英

如何在控制台的activerecord-sqlserver-adapter中调试SQL查询

[英]How to debug sql queries in activerecord-sqlserver-adapter in console

如果有人有几个空闲时间(或几天)来帮助我优化一些通话,并希望为其付费(我可以每小时提供150美元)作为他们的帮助,我真的很希望您的帮助。 我越来越绝望了:)

我有一些很慢的sql查询:

Panel Load (1075.7ms)  EXEC sp_executesql N'SELECT [panels].* FROM [panels] WHERE [panels].[agglo_code_id] = @0 AND [panels].[environment_id] = @1 AND [panels].[product_id] = @2 AND (NOT EXISTS(SELECT 1 FROM campaign_search_panels WHERE campaign_search_panels.panel_id = panels.panel_id AND campaign_search_panels.campaign_id = 32)) AND (NOT EXISTS(SELECT 1 FROM "AIDAAU_Avails" WHERE "AIDAAU_Avails"."PanelID" = panels.panel_uid AND "AIDAAU_Avails"."TillDate" >= ''08-21-2017'' AND "AIDAAU_Avails"."FromDate" <= ''09-03-2017''))', N'@0 int, @1 int, @2 int', @0 = 24, @1 = 14, @2 = 25  [["agglo_code_id", 24], ["environment_id", "14"], ["product_id", "25"]]

我试图弄清楚如何调试它,但我不太正确。 我想对此进行解释,但是由于它已锁定到服务器的ip,因此我无法直接通过sql客户端访问该数据库,因此我试图通过服务器上的rails控制台进行操作。

我可以执行以下操作(不确定为什么要运行两个查询):

irb(main):049:0> ActiveRecord::Base.connection.execute('SELECT [panels].* FROM [panels] WHERE [panels].[agglo_code_id] = 24 AND [panels].[environment_id] = 14 AND [panels].[product_id] = 25 AND (NOT EXISTS(SELECT 1 FROM campaign_search_panels WHERE campaign_search_panels.panel_id = panels.panel_id AND campaign_search_panels.campaign_id = 32)) AND (NOT EXISTS(SELECT 1 FROM "AIDAAU_Avails" WHERE "AIDAAU_Avails"."PanelID" = panels.panel_uid AND "AIDAAU_Avails"."TillDate" >= ''08-21-2017'' AND "AIDAAU_Avails"."FromDate" <= ''09-03-2017''))')
   (47.3ms)  SELECT [panels].* FROM [panels] WHERE [panels].[agglo_code_id] = 24 AND [panels].[environment_id] = 14 AND [panels].[product_id] = 25 AND (NOT EXISTS(SELECT 1 FROM campaign_search_panels WHERE campaign_search_panels.panel_id = panels.panel_id AND campaign_search_panels.campaign_id = 32)) AND (NOT EXISTS(SELECT 1 FROM "AIDAAU_Avails" WHERE "AIDAAU_Avails"."PanelID" = panels.panel_uid AND "AIDAAU_Avails"."TillDate" >= 08-21-2017 AND "AIDAAU_Avails"."FromDate" <= 09-03-2017))
   (47.3ms)  SELECT [panels].* FROM [panels] WHERE [panels].[agglo_code_id] = 24 AND [panels].[environment_id] = 14 AND [panels].[product_id] = 25 AND (NOT EXISTS(SELECT 1 FROM campaign_search_panels WHERE campaign_search_panels.panel_id = panels.panel_id AND campaign_search_panels.campaign_id = 32)) AND (NOT EXISTS(SELECT 1 FROM "AIDAAU_Avails" WHERE "AIDAAU_Avails"."PanelID" = panels.panel_uid AND "AIDAAU_Avails"."TillDate" >= 08-21-2017 AND "AIDAAU_Avails"."FromDate" <= 09-03-2017))
=> 1143

其速度比上述方法快得多,但这是因为我替换了所有标量变量,或者为什么它这么快? 有什么办法可以完全相同地运行查询吗? 即:

query = <<-SQL 
  EXEC sp_executesql N'SELECT [panels].* FROM [panels] WHERE [panels].[agglo_code_id] = @0 AND [panels].[environment_id] = @1 AND [panels].[product_id] = @2 AND (NOT EXISTS(SELECT 1 FROM campaign_search_panels WHERE campaign_search_panels.panel_id = panels.panel_id AND campaign_search_panels.campaign_id = 32)) AND (NOT EXISTS(SELECT 1 FROM "AIDAAU_Avails" WHERE "AIDAAU_Avails"."PanelID" = panels.panel_uid AND "AIDAAU_Avails"."TillDate" >= ''08-21-2017'' AND "AIDAAU_Avails"."FromDate" <= ''09-03-2017''))', N'@0 int, @1 int, @2 int', @0 = 24, @1 = 14, @2 = 25  [["agglo_code_id", 24], ["environment_id", "14"], ["product_id", "25"]]
SQL
ActiveRecord::Base.connection.execute(query)

ActiveRecord::StatementInvalid: TinyTds::Error: Incorrect syntax near '["agglo_code_id", 24'.:

有什么想法可以改进吗?

没有执行计划,将很难诊断出确切的性能问题。 但是,仅查看您的SQL,我就会看到一个巨大的危险信号,这很可能是您的性能问题。

SELECT
    [panels].*
FROM [panels]
WHERE
    [panels].[agglo_code_id] = @0
AND
    [panels].[environment_id] = @1
AND
    [panels].[product_id] = @2
AND
    (
        NOT EXISTS( SELECT 1
                    FROM campaign_search_panels
                    WHERE
                        campaign_search_panels.panel_id = panels.panel_id
                    AND
                        campaign_search_panels.campaign_id = 32)
    )
AND
    (
        NOT EXISTS( SELECT 1
                    FROM AIDAAU_Avails
                    WHERE
                        AIDAAU_Avails.PanelID = panels.panel_uid
                    AND
                        AIDAAU_Avails.TillDate >= '08-21-2017'
                    AND
                        AIDAAU_Avails.FromDate <= '09-03-2017')
    )

当提取动态SQL并使其漂亮时,我发现了两点可能会导致性能问题。 首先,您有一个SELECT * ,它将不管您是否需要从表中获取每一列。 您可能会放慢自己的速度,因为您正在获取比实际需要更多的数据。

第二件事是我巨大的危险信号,即您有两个运行SQL查询的NOT EXISTS子句。 根据三个表之间的数据量,这可能是非常昂贵的操作。 对于主要查询返回的每条记录,您需要运行每个NOT EXISTS查询。 这意味着如果主查询返回100行,则必须运行200个其他查询才能满足where子句。

要解决此问题,您应该可以用两个LEFT JOIN替换那些NOT EXISTS 我可以猜测如何做,但是没有数据可以使用,我不确定,也不想给您带来使情况变得更糟的东西。

为了让您了解性能差异,我进行了一个类似的查询。 由于数据量大,需要36个小时才能运行。 我用某种JOIN替换了子查询,并在不到一个小时的时间内运行了它。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM