内存优化的SQL Server表 - 如何确保表查找?

时间:2015-09-20 04:18:48

标签: sql-server performance tsql memory-optimized-tables

我在获取单列" varchar(5)"时遇到了一些麻烦。字段可靠地使用表搜索而不是表扫描。在这种情况下,生产表包含2500万行。令人印象深刻的是在35秒内扫描2500万行,查询应该运行得更快。

这是部分表格描述

CREATE TABLE [dbo].[Summaries_MO]
(
    [SummaryId] [int] IDENTITY(1,1) NOT NULL,
    [zipcode] [char](5) COLLATE Latin1_General_100_BIN2 NOT NULL,
    [Golf] [bit] NULL,
    [Homeowner] [bit] NULL,
    [IncomeCode] [char](1) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
    [Pets] [bit] NULL,

CONSTRAINT [Summaries_MO_primaryKey] PRIMARY KEY NONCLUSTERED HASH 
(
    [SummaryId]
)WITH ( BUCKET_COUNT = 33554432),
INDEX [ixZIP] NONCLUSTERED 
(
    [zipcode] ASC
)
)WITH ( MEMORY_OPTIMIZED = ON , DURABILITY = SCHEMA_AND_DATA )

通常,使用包含以下内容的查询访问此表:

SELECT ...
            FROM SummaryTable

            WHERE ixZIP IN (SELECT ZipCode FROM @ZipCodesForMO)

此查询坚持使用表扫描。我曾尝试使用WITH(FORCESEEK),但这只会使查询失败。

在我调查此问题时,我也尝试过:

SELECT * FROM Summaries WHERE ZipCode IN ('xxxxx', 'xxxxx', 'xxxxx')

当我使用64个或更少(实际有效)邮政编码运行此查询时,查询使用表搜索。

但是当我给它提供65个或更多的邮政编码时,它会使用表扫描。

总而言之,生产查询始终使用表扫描,当我指定65个或更多邮政编码时,查询也会使用表扫描。

坦率地说,我想知道索引列(Latin1_General_100_BIN2 NOT NULL)的数据类型是否存在问题。我可能会尝试将邮政编码转换为整数以查看会发生什么。

但我宁愿知道发生了什么,而不仅仅是随意尝试。

1 个答案:

答案 0 :(得分:0)

评论时间有点长。

首先,尝试重写为NO

iOS 9

这样做的原因是Sub Send_Email_via_Lotus_Notes(filename as string, emailSubject as string) Dim Maildb As Object Dim MailDoc As Object Dim Body As Object Dim Session As Object 'Start a session of Lotus Notes Set Session = CreateObject("Lotus.NotesSession") 'This line prompts for password of current ID noted in Notes.INI Call Session.Initialize 'or use below to provide password of the current ID (to avoid Password prompt) 'Call Session.Initialize("<password>") 'Open the Mail Database of your Lotus Notes Set Maildb = Session.GETDATABASE("", "D:\Notes\data\Mail\eXceLiTems.nsf") If Not Maildb.IsOpen = True Then Call Maildb.Open 'Create the Mail Document Set MailDoc = Maildb.CREATEDOCUMENT Call MailDoc.REPLACEITEMVALUE("Form", "Memo") 'Set the Recipient of the mail Call MailDoc.REPLACEITEMVALUE("SendTo", "Ashish Jain") 'Set subject of the mail Call MailDoc.REPLACEITEMVALUE("Subject", emailSubject) 'Create and set the Body content of the mail Set Body = MailDoc.CREATERICHTEXTITEM("Body") Call Body.APPENDTEXT("Body text here") 'Example to create an attachment (optional) Call Body.ADDNEWLINE(2) Call Body.EMBEDOBJECT(1454, "", filename, "Attachment") 'Example to save the message (optional) in Sent items MailDoc.SAVEMESSAGEONSEND = True 'Send the document 'Gets the mail to appear in the Sent items folder Call MailDoc.REPLACEITEMVALUE("PostedDate", Now()) Call MailDoc.SEND(False) 'Clean Up the Object variables - Recover memory Set Maildb = Nothing Set MailDoc = Nothing Set Body = Nothing Set Session = Nothing join有更多优化机会。

我认为SQL Server更喜欢全表扫描的原因是因为每个索引查找都需要后跟页面搜索以获取表中的其余列。这使工作量增加了一倍。你有很窄的记录,所以甚至有2500万行可能适合30k左右的页面。

我认为64的截止值太小了。但是,10,000个邮政编码的列表需要阅读大约10,000个页面。通过索引搜索,可以 - 以非常粗略的方式 - 加倍努力。因此,对表的扫描可能合理地具有相似或更好的性能(顺序扫描相对于随机扫描显着优化)。