Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 Помогите с Full-Text Index-ом на большом количестве данных  [new]
sovprene
Member

Откуда:
Сообщений: 3
Добрый день, коллеги.
Столкнулся с такой проблемой:
Есть таблица:
CREATE TABLE [dbo].[MA_Messages](
	[ID] [int] IDENTITY(1,1) NOT NULL,
	[MessageID] [nvarchar](255) NOT NULL,
	[FromID] [int] NULL,
	[Subject] [nvarchar](4000) NULL,
	[Body] [ntext] NULL,
	[dtReceived] [datetime] NOT NULL,
	[HasAttachments] [bit] NOT NULL DEFAULT ((0)),
 CONSTRAINT [PK_MA_Messages_ID] PRIMARY KEY CLUSTERED 
(
	[ID] ASC
)WITH (PAD_INDEX  = OFF, IGNORE_DUP_KEY = OFF, FILLFACTOR = 90) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
Для нее создан Full-Text Index
+ создание индексов

CREATE FULLTEXT INDEX ON [dbo].[MA_Messages_CENTAGE] KEY INDEX [PK_MA_Messages_ID] ON [StevenBCatalog] WITH CHANGE_TRACKING AUTO
ALTER FULLTEXT INDEX ON [dbo].[MA_Messages] ADD ([AttachementNames])
ALTER FULLTEXT INDEX ON [dbo].[MA_Messages] ADD ([Body])
ALTER FULLTEXT INDEX ON [dbo].[MA_Messages] ADD ([MessageID])
ALTER FULLTEXT INDEX ON [dbo].[MA_Messages] ADD ([Subject])
GO
CREATE NONCLUSTERED INDEX [IX_MA_Messages_Date] ON [dbo].[MA_Messages] 
(
	[dtReceived] ASC
)WITH (STATISTICS_NORECOMPUTE  = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = OFF) ON [PRIMARY]
GO

Данных порядка 10 миллионов, а также размер поля Body может быть большим (порядка 10 кб).
Типичный поиск записей проводится в диапазоне дат по заданной поисковой строке по полям Body и Subject:
;WITH MessagesID AS
(
	SELECT ID, ROW_NUMBER() OVER (ORDER BY dtReceived DESC) AS RowNumber
	FROM MA_Messages
	WHERE CONTAINS((Body, Subject), ' "schema*" ') AND  HasAttachments=1 AND dtReceived >= '01.01.2008' AND dtReceived <= '10.10.2008'
)

SELECT	MessagesID.ID,
		Subject,
		CONVERT(nvarchar(200), Body) as Body,
		dtReceived,
		HasAttachments
FROM MessagesID
INNER join MA_Messages AS Messages on Messages.ID=MessagesID.ID
WHERE RowNumber BETWEEN 1 AND 25

Прилагаю план запроса:

+ план запроса
StmtText                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         
--------                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         
Compute Scalar(DEFINE:([Expr1008]=CONVERT(nvarchar(200),[*****_MailArchiver].[dbo].[MA_Messages].[Body] as [Messages].[Body],0)))                                                                                                                                                                                                                                                                                                                                                                
  |--Nested Loops(Inner Join, OUTER REFERENCES:([*****_MailArchiver].[dbo].[MA_Messages].[ID]))                                                                                                                                                                                                                                                                                                                                                                                                  
       |--Filter(WHERE:([Expr1005]>=(1) AND [Expr1005]<=(25)))                                                                                                                                                                                                                                                                                                                                                                                                                                   
       |    |--Top(TOP EXPRESSION:(CASE WHEN (25) IS NULL OR (25)<(0) THEN (0) ELSE (25) END))                                                                                                                                                                                                                                                                                                                                                                                                   
       |         |--Sequence Project(DEFINE:([Expr1005]=row_number))                                                                                                                                                                                                                                                                                                                                                                                                                             
       |              |--Compute Scalar(DEFINE:([Expr1011]=(1)))                                                                                                                                                                                                                                                                                                                                                                                                                                 
       |                   |--Segment                                                                                                                                                                                                                                                                                                                                                                                                                                                            
       |                        |--Sort(ORDER BY:([*****_MailArchiver].[dbo].[MA_Messages].[dtReceived] DESC))                                                                                                                                                                                                                                                                                                                                                                                   
       |                             |--Nested Loops(Inner Join, OUTER REFERENCES:([Full-text Search Engine].[KEY]))                                                                                                                                                                                                                                                                                                                                                                             
       |                                  |--Remote Scan(OBJECT:(CONTAINS))                                                                                                                                                                                                                                                                                                                                                                                                                      
       |                                  |--Clustered Index Seek(OBJECT:([*****_MailArchiver].[dbo].[MA_Messages].[PK_MA_Messages_ID]), SEEK:([*****_MailArchiver].[dbo].[MA_Messages].[ID]=[Full-text Search Engine].[KEY]),  WHERE:([*****_MailArchiver].[dbo].[MA_Messages].[HasAttachments]=(1) AND [*****_MailArchiver].[dbo].[MA_Messages].[dtReceived]>='2008-01-01 00:00:00.000' AND [*****_MailArchiver].[dbo].[MA_Messages].[dtReceived]<='2008-10-10 00:00:00.000') ORDERED FORWARD) 
       |--Clustered Index Seek(OBJECT:([*****_MailArchiver].[dbo].[MA_Messages].[PK_MA_Messages_ID] AS [Messages]), SEEK:([Messages].[ID]=[*****_MailArchiver].[dbo].[MA_Messages].[ID]) ORDERED FORWARD)                                                                                                                                                                                                                                                                                        

Из плана я решил что Full-Text Index - индексирует все записи таблицы. И даже когда поиск осуществляется в интервале дат, Full-Text Index - все равно выбирает записи для всей таблицы, а потом накладывается фильтр по датам.
Я хотел бы чтобы сначала записи фильтровались по датам, а потом среди этих записей производился полнотекстовый поиск.
Подскажите пожалуйста как этого добиться ?
20 май 09, 19:23    [7206097]     Ответить | Цитировать Сообщить модератору
 Re: Помогите с Full-Text Index-ом на большом количестве данных  [new]
sovprene
Member

Откуда:
Сообщений: 3
Чуть не забыл: SQL Server 2005
20 май 09, 19:27    [7206115]     Ответить | Цитировать Сообщить модератору
 Re: Помогите с Full-Text Index-ом на большом количестве данных  [new]
alexeyvg
Member

Откуда: Moscow
Сообщений: 31190
sovprene
Я хотел бы чтобы сначала записи фильтровались по датам, а потом среди этих записей производился полнотекстовый поиск.
Подскажите пожалуйста как этого добиться ?
Перейти на 2008-й...
20 май 09, 22:21    [7206511]     Ответить | Цитировать Сообщить модератору
 Re: Помогите с Full-Text Index-ом на большом количестве данных  [new]
tpg
Member

Откуда: Novosibirsk
Сообщений: 23902
А чем чорт не шутит...
Попробуйте первичный ключ сделать некластерным, а кластерный индекс повесьте на (dtReceived, HasAttachments)...
21 май 09, 06:38    [7207020]     Ответить | Цитировать Сообщить модератору
 Re: Помогите с Full-Text Index-ом на большом количестве данных  [new]
sovprene
Member

Откуда:
Сообщений: 3
alexeyvg
sovprene
Я хотел бы чтобы сначала записи фильтровались по датам, а потом среди этих записей производился полнотекстовый поиск.
Подскажите пожалуйста как этого добиться ?
Перейти на 2008-й...


К сожалению перейти на 2008-й нет возможности...
21 май 09, 15:02    [7210155]     Ответить | Цитировать Сообщить модератору
 Re: Помогите с Full-Text Index-ом на большом количестве данных  [new]
Баранкин
Member

Откуда: из Минска
Сообщений: 75
alexeyvg
Перейти на 2008-й...
и что это даст?
6 окт 09, 18:09    [7749860]     Ответить | Цитировать Сообщить модератору
 Re: Помогите с Full-Text Index-ом на большом количестве данных  [new]
alexeyvg
Member

Откуда: Moscow
Сообщений: 31190
Баранкин
alexeyvg
Перейти на 2008-й...
и что это даст?
В версии 2008 полностью изменена архитектура системы полнотекстовых интексов и поиска. Механизм поиска теперь полностью интегрирован в ядро Dataabse Engine.

В частности, в новой версии для указанной ТС ситуации сервер будет анализировать статистику по таблице, обычным и полнотекстовым индексам и выберет оптимальный план выполнения (искать по обычному индексу, а потом по полнотекстовому, или наоборот).

Более подробно про новую архитектуру: Архитектура компонента Full-Text Search
7 окт 09, 10:20    [7751673]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить