简体   繁体   English

如何提高查询性能

[英]How to improve query performance

I have a lot of records in table. 我在表中有很多记录。 When I execute the following query it takes a lot of time. 当我执行以下查询时,需要花费很多时间。 How can I improve the performance? 如何提高性能?

SET ROWCOUNT 10
SELECT StxnID
      ,Sprovider.description as SProvider
      ,txnID
      ,Request
      ,Raw
      ,Status
      ,txnBal
      ,Stxn.CreatedBy
      ,Stxn.CreatedOn
      ,Stxn.ModifiedBy
      ,Stxn.ModifiedOn
      ,Stxn.isDeleted
  FROM Stxn,Sprovider
  WHERE Stxn.SproviderID = SProvider.Sproviderid
  AND Stxn.SProviderid = ISNULL(@pSProviderID,Stxn.SProviderid)
  AND Stxn.status = ISNULL(@pStatus,Stxn.status)
  AND Stxn.CreatedOn BETWEEN ISNULL(@pStartDate,getdate()-1) and  ISNULL(@pEndDate,getdate())
  AND Stxn.CreatedBy = ISNULL(@pSellerId,Stxn.CreatedBy)  
  ORDER BY StxnID DESC

The stxn table has more than 100,000 records. stxn表有超过100,000条记录。

The query is run from a report viewer in asp.net c#. 查询是从asp.net c#中的报表查看器运行的。

This is my go-to article when I'm trying to do a search query that has several search conditions which might be optional. 当我尝试进行具有多个搜索条件的搜索查询时,这是我的首选文章。

http://www.sommarskog.se/dyn-search-2008.html http://www.sommarskog.se/dyn-search-2008.html

The biggest problem with your query is the column=ISNULL(@column, column) syntax. 查询的最大问题是column=ISNULL(@column, column)语法。 MSSQL won't use an index for that. MSSQL不会使用索引。 Consider changing it to (column = @column AND @column IS NOT NULL) 考虑将其更改为(column = @column AND @column IS NOT NULL)

You should consider using the execution plan and look for missing indexes. 您应该考虑使用执行计划并查找缺少的索引。 Also, how long it takes to execute? 此外,执行需要多长时间? What is slow for you? 什么对你来说很慢?

Maybe you could also not return so many rows, but that is just a guess. 也许你也不能返回那么多行,但这只是猜测。 Actually we need to see your table and indexes plus the execution plan. 实际上我们需要查看您的表和索引以及执行计划。

Check sql-tuning-tutorial 检查sql-tuning-tutorial

For one, use SELECT TOP () instead of SET ROWCOUNT - the optimizer will have a much better chance that way. 首先,使用SELECT TOP ()而不是SET ROWCOUNT - 优化器将有更好的机会。 Another suggestion is to use a proper inner join instead of potentially ending up with a cartesian product using the old style table,table join syntax (this is not the case here but it can happen much easier with the old syntax). 另一个建议是使用正确的内连接,而不是使用旧样式表,表连接语法结束使用笛卡尔积(这不是这里的情况,但使用旧语法可以更容易)。 Should be: 应该:

...
FROM Stxn INNER JOIN Sprovider
  ON Stxn.SproviderID = SProvider.Sproviderid
...

And if you think 100K rows is a lot, or that this volume is a reason for slowness, you're sorely mistaken. 如果你认为100K行很多,或者这个音量是缓慢的原因,那你就错了。 Most likely you have really poor indexing strategies in place, possibly some parameter sniffing, possibly some implicit conversions... hard to tell without understanding the data types, indexes and seeing the plan. 很可能你的索引策略确实很差,可能是一些参数嗅探,可能是一些隐式转换......如果不了解数据类型,索引和查看计划,很难说清楚。

There are a lot of things that could impact the performance of query. 有很多事情可能会影响查询的性能。 Although 100k records really isn't all that many. 虽然100k的记录真的不是那么多。

Items to consider (in no particular order) 要考虑的项目(没有特别的顺序)

Hardware: 硬件:

  1. Is SQL Server memory constrained? SQL Server内存受限吗? In other words, does it have enough RAM to do its job? 换句话说,它有足够的RAM来完成它的工作吗? If it is swapping memory to disk, then this is a sure sign that you need an upgrade. 如果将内存交换到磁盘,则表明您需要升级。
  2. Is the machine disk constrained. 机器磁盘是否受限制。 In other words, are the drives fast enough to keep up with the queries you need to run? 换句话说,驱动器是否足够快以跟上您需要运行的查询? If it's memory constrained, then disk speed becomes a larger factor. 如果内存受限,那么磁盘速度就会变得更大。
  3. Is the machine processor constrained? 机器处理器受到限制吗? For example, when you execute the query does the processor spike for long periods of time? 例如,当您执行查询时,处理器是否会长时间飙升? Or, are there already lots of other queries running that are taking resources away from yours... 或者,是否有很多其他查询正在运行,这些查询正在从您的资源中获取资源......

Database Structure: 数据库结构:

  1. Do you have indexes on the columns used in your where clause? 你在where子句中使用的列上有索引吗? If the tables do not have indexes then it will have to do a full scan of both tables to determine which records match. 如果表没有索引,则必须对两个表进行完全扫描以确定哪些记录匹配。
  2. Eliminate the ISNULL function calls. 消除ISNULL函数调用。 If this is a direct query, have the calling code validate the parameters and set default values before executing. 如果这是直接查询,请让调用代码验证参数并在执行前设置默认值。 If it is in a stored procedure, do the checks at the top of the s'proc. 如果它在存储过程中,请执行s'proc顶部的检查。 Unless you are executing this with RECOMPILE that does parameter sniffing, those functions will have to be evaluated for each row.. 除非您使用执行参数嗅探的RECOMPILE执行此操作,否则必须为每一行评估这些函数。

Network: 网络:

  1. Is the network slow between you and the server? 你和服务器之间的网络速度慢吗? Depending on the amount of data pulled you could be pulling GB's of data across the wire. 根据提取的数据量,您可以通过线路提取GB的数据。 I'm not sure what is stored in the "raw" column. 我不确定“raw”列中存储了什么。 The first question you need to ask here is "how much data is going back to the client?" 你需要问的第一个问题是“有多少数据会回到客户端?” For example, if each record is 1MB+ in size, then you'll probably have disk and network constraints at play. 例如,如果每条记录的大小为1MB +,那么您可能会遇到磁盘和网络限制。

General: 一般:

  1. I'm not sure what "slow" means in your question. 我不确定你的问题中“慢”意味着什么。 Does it mean that the query is taking around 1 second to process or does it mean it's taking 5 minutes? 是否意味着查询需要大约1秒才能处理,或者是否意味着需要5分钟? Everything is relative here. 这里的一切都是相对的。

Basically, it is going to be impossible to give a hard answer without a lot of questions asked by you. 基本上,如果没有你提出的很多问题,就不可能给出一个难以回答的答案。 All of these will bear out if you profile the queries, understand what and how much is going back to the client and watch the interactions amongst the various parts. 如果您分析查询,了解返回客户端的内容和数量,并观察各个部分之间的交互,所有这些都将证明。

Finally depending on the amount of data going back to the client there might not be a way to improve performance short of hardware changes. 最后,根据返回客户端的数据量,可能无法在没有硬件更改的情况下提高性能。

Make sure Stxn.SproviderID, Stxn.status, Stxn.CreatedOn, Stxn.CreatedBy, Stxn.StxnID and SProvider.Sproviderid all have indexes defined. 确保Stxn.SproviderID,Stxn.status,Stxn.CreatedOn,Stxn.CreatedBy,Stxn.StxnID和SProvider.Sproviderid都定义了索引。

(NB -- you might not need all, but it can't hurt.) (注意 - 你可能不需要所有,但它不会受到伤害。)

I don't see much that can be done on the query itself, but I can see things being done on the schema : 我没有看到可以对查询本身做多少,但我可以看到在架构上完成的事情:

  • Create an index / PK on Stxn.SproviderID 在Stxn.SproviderID上创建索引/ PK
  • Create an index / PK on SProvider.Sproviderid 在SProvider.Sproviderid上创建索引/ PK
  • Create indexes on status, CreatedOn, CreatedBy, StxnID 在状态,CreatedOn,CreatedBy,StxnID上创建索引

Something to consider: When ROWCOUNT or TOP are used with an ORDER BY clause, the entire result set is created and sorted first and then the top 10 results are returned. 需要考虑的事项:当ROWCOUNT或TOP与ORDER BY子句一起使用时,首先创建并排序整个结果集,然后返回前10个结果。

How does this run without the Order By clause? 如果没有Order By子句,它如何运行?

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

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