简体   繁体   English

改善SQL查询的性能

[英]Improving the performance of an SQL query

I have a SQL Server table containing around 50,000,000 rows and I need to run the following two queries on it: 我有一个包含约50,000,000行的SQL Server表,我需要对其运行以下两个查询:

SELECT  Count(*) AS Total
FROM    TableName WITH(NOLOCK)
WHERE   Col1 = 'xxx' AND Col2 = 'yyy'

then 然后

SELECT  TOP 1   Col3
FROM            TableName WITH(NOLOCK)
WHERE           Col1 = 'xxx' AND Col2 = 'yyy'
ORDER BY        TableNameId DESC

The table has the following structure: 该表具有以下结构:

dbo.TableName
TableNameId  int PK
Col1         varchar(12)
Col2         varchar(256)
Col3         int
Timestamp    datetime

As well as running queries on it, there are loads of inserts every second going into the table hence the NOLOCK. 除了在其上运行查询外,每秒还会有大量插入插入表中,因此会产生NOLOCK。 I've tried creating the following index: 我尝试创建以下索引:

NONCLUSTERED INDEX (Col1, Col2) INCLUDE (TableNameId, Col3)

I need these queries to return results as quick as possible (1 second max). 我需要这些查询以尽快返回结果(最大1秒)。 At this stage, I have the ability to restructure the table as the data isn't live yet, and I can also get rid of the Timestamp field if I need to. 在这个阶段,我可以重组表,因为数据还不存在,如果需要的话,我也可以摆脱Timestamp字段。

Firstly - include TableNameID in your index and not as included column, then you can specify descending in the index order. 首先-将TableNameID包含在索引中而不是包含列中,然后可以descending索引顺序指定descending

That should speed up things regarding your TOP 1 ... ORDER BY TableNameId DESC 那应该加快与您的TOP 1 ... ORDER BY TableNameId DESC有关的事情TOP 1 ... ORDER BY TableNameId DESC

Secondly - check up on how much time is I/O for example (SET STATISTICS IO ON) and how much is CPU (SET STATISTICS TIME ON). 其次-检查例如I / O有多少时间(SET STATISTICS IO ON)和CPU有多少时间(SET STATISTICS TIME ON)。 If it is I/O there's not much you can do because you do have to move through a lot of data. 如果是I / O,那么您将无能为力,因为您必须浏览大量数据。

If you'd like a very fast estimate of how many rows are in the table, try quering sys.dm_db_partition_stats : 如果您想快速估算表中有多少行,请尝试查询sys.dm_db_partition_stats

-- Report how many rows are in each table
SELECT o.name as [Table Name], ddps.row_count 
FROM sys.indexes (nolock) AS i 
 INNER JOIN sys.objects (nolock) AS o ON i.OBJECT_ID = o.OBJECT_ID 
 INNER JOIN sys.dm_db_partition_stats (nolock) AS ddps ON i.OBJECT_ID = ddps.OBJECT_ID 
 AND i.index_id = ddps.index_id 
WHERE i.index_id < 2 
 AND o.is_ms_shipped = 0   -- Remove to include system objects 
 AND ddps.row_count > 0
ORDER BY ddps.row_count DESC

If you have multiple partitions, this may not work. 如果您有多个分区,则可能无法正常工作。 You might need to get the SUM of the row_count . 您可能需要获取row_countSUM

However, if you need an accurate count, you will need to count the rows, and this will take a while. 但是,如果需要准确的计数,则需要对行进行计数,这将需要一段时间。 Also, you may get the error "Could not continue scan with NOLOCK due to data movement." 另外,您可能会收到错误“由于数据移动,无法继续使用NOLOCK进行扫描”。

You didn't mention how long your indexed query is running. 您没有提到索引查询运行了多长时间。 The index and your query look fine to me. 该索引和您的查询对我来说很好。

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

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