简体   繁体   English

需要优化选择查询

[英]Need to optimise select query

I have a query that does a select with joins from multiple tables that contains in total about 90 million rows.我有一个查询,它使用来自多个表的连接进行选择,这些表总共包含大约 9000 万行。 I only need data from the last 30 days.我只需要过去 30 天的数据。 The problem is that when I run the select query the sql server throws a timeout while the query is running and new records are not created during this time frame.问题是,当我运行选择查询时,sql server 在查询运行时抛出超时,并且在此时间范围内没有创建新记录。 This query takes about 5 seconds to complete.此查询大约需要 5 秒才能完成。

I would like to optimise this query so that it wont go through the entire tables looking at the datetime and would only search from the latest entries.我想优化此查询,使其不会遍历查看日期时间的整个表,而只会从最新条目中搜索。

Right now it seems that I would need to index datetime column.现在看来我需要索引日期时间列。 Please advise if I need to create indexes or if there is another way to optimise this query.请告知我是否需要创建索引或者是否有其他方法可以优化此查询。

SELECT [table1].Column1 AS InvoiceNo,
       'ND' AS VATRegistrationNumber,
       'ND' AS RegistrationNumber,
       Column2 AS Country,
       [table2].Column3 + ' ' + [table2].Column4 AS Name,
       CAST([table1].Column5 AS date) AS InvoiceDate,
       'SF' AS InvoiceType,
       '' AS SpecialTaxation,
       '' AS VATPointDate,
       ROUND([table1Line].Column6, 2) AS TaxableValue,
       CASE
            WHEN [table1Line].Column7 = 9 THEN 'PVM2'
            WHEN [table1Line].Column7 = 21 THEN 'PVM1'
            WHEN [table1Line].Column7 = 0 THEN 'PVM14'
       END AS TaxCode,
       CAST([table1Line].Column7 AS int) AS TaxPercentage,
       table1Line.Column8 - ROUND([table1Line].Column6, 2) AS Amount,
       '' AS VATPointDate2,
       [table1].Column1 AS InvoiceNo,
       '' AS ReferenceNo,
       '' AS ReferenceDate,
       [table1].CustomerPersonID AS CustomerID
FROM [table1]
     INNER JOIN [table2] ON [table1].CustomerPersonID = [table2].ID
     INNER JOIN [table3] ON [table2].Column9 = [table3].ID
     INNER JOIN [table1Line] ON [table1].ID = [table1Line].table1ID
     INNER JOIN [table4] ON table1Line.TaxID = Tax.ID
     INNER JOIN [table5] ON [table1].CompanyID = Company.ID
     INNER JOIN table6 ON [table1].SalesChannelID = table6.ID
WHERE Column5 LIKE '%date%'
  AND table6.id = 5
   OR table6.id = 2
  AND Column5 LIKE '%date%'
ORDER BY Column5 DESC;

First things first, each database runs a little differently because the optimizer has been running and figuring out how the unique circumstances can be improved and continuously tries to make common things run better.首先,每个数据库的运行方式略有不同,因为优化器一直在运行,并找出如何改进独特的环境,并不断尝试使常见的事情运行得更好。

There's also versioning differences that also play a part is the performance of the server.服务器的性能也存在版本差异。

Besides that stuff, Here's a few things to do to optimize this query.除了这些东西,还有一些事情要做来优化这个查询。 When working with Joins, Your Joined table comes first then compare against the already specified table.使用联接时,您的联接表首先出现,然后与已指定的表进行比较。

For example t2 checks against t1:例如 t2 检查 t1:

select t1.name, t2.car
from customers as t1
left join purchases as t2
on t2.customerid = t1.customerid

The next thing I see is the Like condition in the Where part of the code.接下来我看到的是代码 Where 部分中的 Like 条件。
The stored date that it's finding is stored as text in your example.它发现的存储日期在您的示例中存储为文本。
I would recommend processing the date as a datetime instead of a string type of datatype.我建议将日期处理为日期时间而不是字符串类型的数据类型。

I would include that in the code below, but I'm not sure what the format looks like for your string of text.我会将其包含在下面的代码中,但我不确定您的文本字符串的格式是什么样的。

%date% is the same thing as saying "Contains date". %date% 与说“包含日期”相同。
This takes the date string, and tries to see if it matches in every position of characters from left to right.这需要日期字符串,并尝试查看它是否匹配从左到右的每个字符位置。

So if your date text is 20200130, it will check to see if it matches 2date0200130, then tries 20date200130, then tries 202date00130, etc.因此,如果您的日期文本是 20200130,它将检查它是否匹配 2date0200130,然后尝试 20date200130,然后尝试 202date00130,等等。
It will significantly increase the time it takes to process.它将显着增加处理所需的时间。

I also see that the date is being searched accidently two times instead of one.我还看到日期被意外搜索了两次而不是一次。

I would recommend doing:我建议这样做:

WHERE LTRIM(RTRIM(Column5)) LIKE 'date'

As for the Inner Joins, I would not use them.至于内连接,我不会使用它们。 Use the Left join, and then in the Where, I would make sure it had no Null values for that joined data.使用左连接,然后在 Where 中,我会确保该连接数据没有 Null 值。
This makes the Left Join work the same as the Inner Join and runs more optimally when you are running the query.这使得 Left Join 与 Inner Join 的工作方式相同,并且在您运行查询时运行得更优化。

For Instance, the first Join would look like this:例如,第一个 Join 如下所示:

FROM [table1]
LEFT JOIN [table2] ON [table2].ID = [table1].CustomerPersonID
WHERE table2.id IS NOT NULL

I see an error in the code in the Where statement:我在 Where 语句的代码中看到错误:

AND table6.id = 5
OR tables6.id = 2

This should be:这应该是:

AND (tables6.id = 5 OR tables6.id = 2)

So here should be an optimized version of your code:所以这里应该是你的代码的优化版本:

SELECT [table1].Column1 AS InvoiceNo,
'ND' AS VATRegistrationNumber,
'ND' AS RegistrationNumber,
Column2 AS Country,
[table2].Column3 + ' ' + [table2].Column4 AS Name,
CAST([table1].Column5 AS date) AS InvoiceDate,
'SF' AS InvoiceType,
'' AS SpecialTaxation,
'' AS VATPointDate,
ROUND([table1Line].Column6, 2) AS TaxableValue,
(CASE WHEN [table1Line].Column7 = 9 THEN 'PVM2'
      WHEN [table1Line].Column7 = 21 THEN 'PVM1'
      WHEN [table1Line].Column7 = 0 THEN 'PVM14'
      ELSE '' END ) AS TaxCode,
CAST([table1Line].Column7 AS int) AS TaxPercentage,
table1Line.Column8 - ROUND([table1Line].Column6, 2) AS Amount,
'' AS VATPointDate2,
[table1].Column1 AS InvoiceNo,
'' AS ReferenceNo,
'' AS ReferenceDate,
[table1].CustomerPersonID AS CustomerID
FROM [table1]
LEFT JOIN [table2] ON [table2].ID = [table1].CustomerPersonID
LEFT JOIN [table3] ON [table3].ID = [table2].Column9
LEFT JOIN [table1Line] ON [table1Line].table1ID = [table1].ID
LEFT JOIN [table4] ON [table4].ID = table1Line.TaxID
LEFT JOIN [table5] ON [table5].ID = [table1].CompanyID
LEFT JOIN [table6] ON table6.ID = [table1].SalesChannelID
WHERE table2.ID IS NOT null
AND table3.ID IS NOT null
AND table1Line.ID IS NOT null
AND table4.ID IS NOT null
AND table5.ID IS NOT null
AND table6.ID IS NOT null
AND LTRIM(RTRIM(Column5)) LIKE 'date'
AND (table6.id = 5 OR table6.id = 2)
ORDER BY Column5 DESC;  

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

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