【问题标题】:Best way to optimize this SQL Query优化此 SQL 查询的最佳方法
【发布时间】:2015-10-09 00:58:13
【问题描述】:

我必须优化这个查询,我真的很着急。以下查询按客户端搜索。输入值RIF.keyvaluechar LIKE 'V%10553790 ' 是因为在数据库中的一些旧寄存器中,某些 ID 在缺少字符时曾经是 V0012345678,但它应该是 V12345678,因为这是 ID 可以具有的最大字符数。我知道 12345678 应该是数字,而 V 是一个字符,然后进行比较,但这是另一个问题。

反正查询就是这个:

SELECT DISTINCT idata.itemnum AS [ID], 
                LTRIM(RTRIM(ISNULL(CONTRATO.keyvaluechar,'N/A'))) AS [Contrato],
                idata.datestored AS [Fecha], 
                NUMERO.keyvaluesmall AS [Numero], 
                TIPO.keyvaluechar AS [Tipo], 
                LTRIM(RTRIM(ISNULL(LC.lifecyclename,'N/A'))) AS [Flujo], 
                LTRIM(RTRIM(ISNULL(LC.lcnum,-1))) AS [FlujoID], 
                LTRIM(RTRIM(ISNULL(LCS.statename,'N/A'))) AS [Cola], 
                LTRIM(RTRIM(ISNULL(LCS.statenum,-1))) AS [ColaID], 
                CASE 
                    WHEN PC.NombreProceso IN('PTD','PV2','PV3') THEN 1 
                    ELSE 0 
                END AS [Portada] 
FROM OnBase.hsi.itemdata idata WITH (NOLOCK) 
    INNER JOIN OnBase.hsi.keyitem109 TIPO WITH (NOLOCK) ON TIPO.itemnum = idata.itemnum 
    INNER JOIN OnBase.hsi.keyitem113 NUMERO WITH (NOLOCK) ON NUMERO.itemnum = idata.itemnum 
    LEFT JOIN OnBase.hsi.keyitem132 CONTRATO WITH (NOLOCK) ON CONTRATO.itemnum = idata.itemnum 
    LEFT JOIN OnBase.hsi.keyitem114 CLIENTE WITH (NOLOCK) ON CLIENTE.itemnum = idata.itemnum 
    LEFT JOIN OnBase.hsi.keyitem111 RIF WITH (NOLOCK) ON RIF.itemnum = idata.itemnum 
    INNER JOIN OnBase.hsi.doctype DOC WITH (NOLOCK) ON DOC.itemtypenum = idata.itemtypenum 
    INNER JOIN BD_WorkFlow.dbo.BBVA_ProcesosConfig PC WITH (NOLOCK) ON PC.ID_Documento = idata.itemtypenum 
    LEFT JOIN Onbase.hsi.itemlc ILC WITH (NOLOCK) ON ILC.itemnum = idata.itemnum 
    LEFT JOIN Onbase.hsi.lcstate LCS WITH (NOLOCK) ON LCS.statenum = ILC.statenum 
    LEFT JOIN Onbase.hsi.lifecycle LC WITH (NOLOCK) ON LC.lcnum = ILC.lcnum 
WHERE PC.NombreProceso <> 'XXX' AND 
      PC.NombreProceso NOT IN('PTD','PV2','PV3') AND 
      TIPO.keyvaluechar = 'CCD' AND 
      RIF.keyvaluechar LIKE 'V%10553790 '

如您所见,它是这种方式,所以它会找到 V0012345678 或 V12345678,但这不是正确的方式,或者我觉得这是最好的优化,虽然我不是数据库专家。

无论如何,我已经考虑过类似这样的事情而不是最后一行

AND LEFT ('RIF.Keyvaluechar, 1) ="V"
AND SUBSTRING (RIF.Keyvaluechar, 2, LEN(RIF.Keyvaluechar)) = "12345678"

你们怎么看?有没有其他更好的方法来改进这一点?

【问题讨论】:

  • 您在 RIF 上进行了左连接,只是稍后使用 where 子句将其过滤掉。为什么不将该条件添加到 Join 并使其成为 Inner join?
  • 除了检查它是否存在之外,您似乎并没有真正使用CLIENTE。查看该表以查看您是否真的需要它,如果需要,则可以使用内部联接或 EXISTS 检查来检查该表中是否存在 itemnum。还有你在OnBase.hsi.itemdata 上有什么样的索引?索引可以帮助优化查询。
  • 当 PC.NombreProceso 被排除在 where 子句中时,为什么要检查它们是否为 IN ('PTD','PV2','PV3')?为什么不在 NOT IN 条件中加上“xxx”?
  • 附带说明一下,在使用 NOLOCK 提示乱扔数据库之前,您可以先看看这篇文章。 blogs.sqlsentry.com/aaronbertrand/bad-habits-nolock-everywhere

标签: sql sql-server optimization


【解决方案1】:

首先,您的查询存在逻辑问题。你有这个:

LEFT JOIN OnBase.hsi.keyitem111 RIF WITH(NOLOCK) ON RIF.itemnum = idata.itemnum 

然后在你的where 子句中:

AND RIF.keyvaluechar LIKE 'V%10553790 '

将该过滤器放入您的where 子句中可以有效地将您的左连接更改为内连接。要解决此问题,请将过滤器移至联接。

在优化方面,我认为这意味着让它运行得更快。您正在考虑的内容可能会减慢速度,因为您正在过滤函数结果而不是字段。无论您多么着急,一个更好的方法是查看数据库中的索引并尝试过滤这些索引。事实上,添加新的可能是合适的。

【讨论】:

    【解决方案2】:

    Keyvaluechar 是否总是从第二个字符开始的数字,并且您希望将其视为数字(=删除前导零)。您可以尝试将持久列 convert(int, SUBSTRING (Keyvaluechar, 2, 10)) 添加到表中,然后对其进行索引,并将其用作搜索条件。至少我认为这应该会有很大帮助。

    除此之外,查看统计信息 IO 输出可能也是一个好主意,看看哪个表实际上负责最大的 I/O 量。

    请注意,我希望您也知道使用 NOLOCK 可能导致的问题。

    【讨论】:

    • 我没有做这个代码或查询,我只是想优化它。我上面给出的选项将时间从 59 秒减少到 7 秒,但它没有返回我想要的代码,因为它在有 00 时删除了它,但当没有时,它正在删除它。我会尝试一些有条件的
    • @Swimcito 抱歉无法真正理解您要说的内容,但如果问题是您只需要比较字符串的结尾,您可以使用反向计算列,然后还反转您的搜索字符串,并使用类似 '87654321%' - 我知道这很难看,但它可能会工作;)
    猜你喜欢
    • 1970-01-01
    • 2014-07-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多