我在SQL Server 2008数据库中有一个非常大的表,包含4000万行。
CREATE TABLE [dbo].[myTable](
[ID] [bigint] NOT NULL,
[CONTRACT_NUMBER] [varchar](50) NULL,
[CUSTOMER_NAME] [varchar](200) NULL,
[INVOICE_NUMBER] [varchar](50) NULL,
[AGENCY] [varchar](50) NULL,
[AMOUNT] [varchar](50) NULL,
[INVOICE_MONTH] [int] NULL,
[INVOICE_YEAR] [int] NULL,
[Unique_ID] [bigint] NULL,
[bar_code] [varchar](50) NOT NULL,
CONSTRAINT [PK_MyTable] PRIMARY KEY CLUSTERED
(
[ID] ASC,
[bar_code] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
我正在尝试优化以下查询的效果:
SELECT top 35 ID,
CONTRACT_NR,
CUSTOMER_NAME,
INVOICE_NUMBER,
AMOUNT,
AGENCY,
CONTRACT_NUMBER,
ISNULL([INVOICE_MONTH], 1) as [INVOICE_MONTH],
ISNULL([INVOICE_YEAR], 1) as [INVOICE_YEAR],
bar_code,
Unique_ID
from MyTable
WHERE
CONTRACT_NUMBER like @CONTRACT_NUMBER and
INVOICE_NUMBER like @INVOICE_NUMBER and
CUSTOMER_NAME like @CUSTOMER_NAME
ORDER BY Unique_ID desc
为了做到这一点,我在列CONTRACT_NUMBER,INVOICE_NUMBER和CUSTOMER_NAME上构建了一个包含的索引。
CREATE NONCLUSTERED INDEX [ix_search_columns_without_uniqueid] ON [dbo].[MyTable]
(
[CONTRACT_NUMBER] ASC,
[CUSTOMER_NAME] ASC,
[INVOICE_NUMBER] ASC
)
INCLUDE ( [ID],
[AGENCY],
[AMOUNT],
[INVOICE_MONTH],
[INVOICE_YEAR],
[Unique_ID],
[Contract_nr],
[bar_code]) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
仍然需要执行3秒到10秒的查询。从查询执行计划中我看到索引搜索操作正在消耗大约30%的总工作负载而不是排序(前N)操作消耗其他70%。任何想法如何优化此查询,响应时间小于1秒是首选? 注意:我还尝试在索引列中包含dhe列[Unique_ID]。在这种情况下,查询执行计划正在进行索引扫描,但是由于许多用户查询数据库,我遇到了同样的问题。
答案 0 :(得分:1)
查看此page了解更多详情。
UPDATE STATISTICS tablename WITH fullscan
GO
设置统计时间并执行以下查询
SET STATISTICS time ON
GO
SELECT num_of_reads, num_of_bytes_read,
num_of_writes, num_of_bytes_written
FROM sys.dm_io_virtual_file_stats(DB_ID('tempdb'), 1)
GO
SELECT TOP 100 c1, c2,c3
FROM yourtablename
WHERE c1<30000
ORDER BY c2
GO
SELECT num_of_reads, num_of_bytes_read,
num_of_writes, num_of_bytes_written
FROM sys.dm_io_virtual_file_stats(DB_ID('tempdb'), 1)
GO
<强>结果强>
CPU time = 124 ms, elapsed time = 91 ms
Before Query execution
num_of_reads num_of_bytes_read num_of_writes num_of_bytes_written
-------------------- -------------------- -------------------- --------------------
725864 46824931328 793589 51814416384
After Query execution
num_of_reads num_of_bytes_read num_of_writes num_of_bytes_written
-------------------- -------------------- -------------------- --------------------
725864 46824931328 793589 51814416384
来源:https://www.mssqltips.com/sqlservertip/2053/trick-to-optimize-top-clause-in-sql-server/
答案 1 :(得分:0)
尝试将您的聚集索引(当前在两列上)替换为unique_id
上的一个(假设它确实是唯一的)。这有助于您的分类。然后在WHERE
中使用的三个列上添加第二个覆盖索引 - 正如您所尝试的那样。检查您的统计信息是否是最新的。我有一种感觉,PK中的bar_code
列阻止你的排序尽可能快地运行。
您的变量是否包含通配符?如果它们包含通配符,则无法使用WHERE列上的索引。如果他们不是通配符,请尝试直接"="
,假设区分大小写不是问题。
更新:由于您拥有前导通配符,因此您将无法利用CONTRACT_NUMBER
,INVOICE_NUMBER
或CUSTOMER_NAME
上的索引:作为GriGrim建议,这里唯一的选择是使用全文搜索(CONTAINS
关键字等。)。