Я пытаюсь выполнить полное внешнее соединение двух не связанных таблиц. У каждой таблицы есть location_id, который в конечном итоге сформирует отношения первичного / внешнего ключа (как только я выясню эту проблему с производительностью). При выполнении внешнего соединения он просто отсчитывает время. Запросы и триггеры, выполняемые для каждой таблицы отдельно, выполняются менее чем за секунду.

В этой таблице 21000 записей:

CREATE TABLE [dbo].[TBL_LOCATIONS](
    [OBJECTID] [int] NOT NULL,
    [Loc_Name] [nvarchar](100) NULL,
    [Location_ID] [uniqueidentifier] NULL,
    [SHAPE] [geometry] NULL,

 CONSTRAINT [R33_pk] PRIMARY KEY CLUSTERED 
(
    [OBJECTID] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON, FILLFACTOR = 75) ON [PRIMARY]
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[TBL_LOCATIONS]  WITH CHECK ADD  CONSTRAINT [g17_ck] CHECK  (([SHAPE].[STSrid]=(26917)))
GO
ALTER TABLE [dbo].[TBL_LOCATIONS] ADD  CONSTRAINT [DF_TBL_LOCATIONS_Location_ID]  DEFAULT (newsequentialid()) FOR [Location_ID]
GO

CREATE SPATIAL INDEX [S17_idx] ON [dbo].[TBL_LOCATIONS] 
(
    [SHAPE]
)USING  GEOMETRY_GRID 
WITH (
BOUNDING_BOX =(224827, 3923750, 323464, 3967780), GRIDS =(LEVEL_1 = HIGH,LEVEL_2 = HIGH,LEVEL_3 = HIGH,LEVEL_4 = HIGH), 
CELLS_PER_OBJECT = 16, PAD_INDEX  = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
GO

CREATE UNIQUE NONCLUSTERED INDEX [UUID_OID_33] ON [dbo].[TBL_LOCATIONS] 
(
    [Location_ID] ASC,
    [OBJECTID] ASC
)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, FILLFACTOR = 75) ON [PRIMARY]
GO

В этой таблице 53000 записей

CREATE TABLE [dbo].[TBL_EVENTS](
    [OBJECTID] [int] NOT NULL,
    [Event_ID] [uniqueidentifier] NULL,
    [Location_ID] [uniqueidentifier] NULL,
 CONSTRAINT [PK_TBL_EVENTS] PRIMARY KEY CLUSTERED 
(
    [OBJECTID] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[TBL_EVENTS] ADD  CONSTRAINT [DF_TBL_EVENTS_Event_ID]  DEFAULT (newsequentialid()) FOR [Event_ID]
GO
ALTER TABLE [dbo].[TBL_EVENTS] ADD  CONSTRAINT [DF_TBL_EVENTS_Event_ID]  DEFAULT (newsequentialid()) FOR [Event_ID]
GO

CREATE UNIQUE NONCLUSTERED INDEX [R36_SDE_ROWID_UK] ON [dbo].[TBL_EVENTS] 
(
    [OBJECTID] ASC
)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, FILLFACTOR = 75) ON [PRIMARY]
GO

А вот запрос, который выполняется ... и выполняется ... 1 час, а результатов нет.

SELECT     
    TBL_LOCATIONS.Loc_Name, 
    TBL_LOCATIONS.Location_ID, 
    TBL_LOCATIONS.SHAPE, 
    TBL_EVENTS.Event_ID
FROM         
    TBL_EVENTS 
FULL OUTER JOIN
    TBL_LOCATIONS ON TBL_EVENTS.Location_ID = TBL_LOCATIONS.Location_ID

Я пробовал каждую перестановку индексов атрибутов в обеих таблицах, перестраивая и реорганизуя их, ничего не влияет на производительность. Использование ObjectID в качестве PK разрешено приложением, как и последовательный идентификатор GUID. Я не думаю, что это факторы здесь, поскольку обе эти таблицы прекрасно работают вне этого запроса. SQL Server 2008 SP1 64BIT на RAID 10/48 ГБ RAM.

1
tpcolson 5 Мар 2012 в 23:59

3 ответа

Лучший ответ

FULL JOIN хорошо работает, когда данные в столбцах, используемых для связывания таблиц, уникальны.

Для строк, содержащих повторяющиеся данные, FULL JOIN ведет себя как CROSS JOIN и может вызвать проблемы с производительностью.

Так что, вероятно, узкое место происходит из-за дубликатов в столбце LOCATION_ID.

2
Radek 5 Мар 2012 в 20:44

Возможно, вам стоит подумать об отключении журнала транзакций, пока вы все это делаете.

2
YS. 5 Мар 2012 в 20:10

Если значения связанных полей не так уж уникальны (местоположение), размер запроса может приблизиться к довольно большому числу.

В крайнем примере, если бы для местоположения в обеих таблицах было только значение «1», общее количество строк было бы близко к размеру перекрестного соединения, примерно 1113000000 строк (21000 * 53000). Запрос такого размера (более миллиарда строк) займет много времени.

РЕДАКТИРОВАТЬ - обновление неправильного оператора, как указано в комментариях

1
Chris Young 5 Мар 2012 в 20:45