Вы можете использовать exec для запуска объектов кода. Например, если вы определили f, как указано выше, то
exec(f.func_code.co_consts[3])
выдаст
get
в качестве вывода.
даты во вложенном цикле. Если ваши данные распределены наоборот, то есть у вас много строк в A
, но мало в B
, и диапазоны в общем коротко, тогда вы можете немного изменить дизайн своих таблиц:
A
start_date interval_length
, создать составной индекс на A (interval_length, start_date)
и использовать этот запрос:
SELECT *
FROM (
SELECT DISTINCT interval_length
FROM a
) ai
CROSS JOIN
b
JOIN a
ON a.interval_length = ai.interval_length
AND a.start_date BETWEEN b.date - ai.interval_length AND b.date
В каждой версии sql server 2000, 2005, 2008 есть программа под названием советник по настройке DataBase, когда вы запускаете какой-либо запрос, он сообщает вам, какие индексы вам нужно добавить, чтобы получить запрос быстрее С уважением, Иордан
Я работал в двух компаниях (которые занимаются системами управления временем и посещаемостью), которые часто используют столбцы startDate и endDate. По моему опыту, не существует хороших индексов, которые всегда работают с диапазонами дат .
Попробуйте использовать такие индексы, как (startDate, -endDate) и (-endDate, startDate), чтобы увидеть, помогают ли они , многое зависит от того, на что похожи данные в таблице . Например, если у вас есть много старых строк с endDate перед искомыми датами, может помочь принудительное использование Sql индекса на основе (endDate, startDate).
Также попробуйте использовать индекс, охватывающий все столбцы, которые находятся в вашем операторе «where», поэтому sql не нужно читать основную таблицу, пока он не определит, какие строки возвращать.
Вы можете использовать подсказки индекса, поскольку маловероятно, что обработчик запросов знает о данных достаточно, чтобы сделать правильный выбор индексов - это один из очень немногих случаев, когда мне приходилось учитывать подсказки индекса.
Расширение данных, Итак, у вас есть таблица, которая содержит (дату, в строке) со строкой для каждой даты в диапазоне дат , может потребоваться . Однако поддерживать "индексную" таблицу в обновленном состоянии - это проблема.
Если вы знаете, что некоторые из ваших диапазонов дат не перекрываются, взгляните на Использование CROSS APPLY для оптимизации объединений по условиям МЕЖДУ (например, медицинские записи сотрудника не должны перекрываться)
В конце концов, если у вас всего несколько тысяч записей, полное сканирование таблицы не так уж плохо.
Quassnoi субъектов с использованием ПРОСТРАНСТВЕННЫХ индексов , У меня нет опыта "злоупотребления" пространственными индексами подобным образом, но я думаю, что попробовать стоит. Однако будьте очень осторожны, если вам придется поддерживать несколько поставщиков баз данных, поскольку пространственные индексы довольно новы. Также вам могут понадобиться столбцы дат для инструментов отчетности и т. Д.
(Рано или поздно нужно будет найти все строки, которые перекрывают диапазон дат, тогда станет еще труднее получить индексы, дающие хорошие результаты.)
Вам нужно 3 индекса A.startDate, B.dates и A.endDate, может быть индекс (A.endDate + A.startDate) тоже подойдет. У меня нет подробностей о других столбцах и назначении этих таблиц, но я рассматриваю возможность использования кластерного индекса.
В любом случае используйте параметр «План выполнения», чтобы принять решение между всеми этими вариантами, потому что мое предложение слишком общее
Следующий скрипт перечислит возможные отсутствующие индексы (вы можете отфильтровать инструкцию по t.name).
SELECT t.name AS 'affected_table',
'Create NonClustered Index IX_' + t.name + '_missing_' + CAST(ddmid.index_handle AS VARCHAR(10)) + ' On ' + ddmid.STATEMENT + ' (' + ISNULL(ddmid.equality_columns, '') +
CASE
WHEN ddmid.equality_columns IS NOT NULL
AND ddmid.inequality_columns IS NOT NULL
THEN ','
ELSE ''
END + ISNULL(ddmid.inequality_columns, '') + ')' + ISNULL(' Include (' + ddmid.included_columns + ');', ';') AS sql_statement,
ddmigs.user_seeks,
ddmigs.user_scans,
CAST((ddmigs.user_seeks + ddmigs.user_scans) * ddmigs.avg_user_impact AS INT) AS 'est_impact',
ddmigs.last_user_seek
FROM sys.dm_db_missing_index_groups AS ddmig
INNER JOIN sys.dm_db_missing_index_group_stats AS ddmigs
ON ddmigs.group_handle = ddmig.index_group_handle
INNER JOIN sys.dm_db_missing_index_details AS ddmid
ON ddmig.index_handle = ddmid.index_handle
INNER JOIN sys.tables AS t
ON ddmid.OBJECT_ID = t.OBJECT_ID
WHERE ddmid.database_id = DB_ID()
AND CAST((ddmigs.user_seeks + ddmigs.user_scans) * ddmigs.avg_user_impact AS INT) > 100
ORDER BY CAST((ddmigs.user_seeks + ddmigs.user_scans) * ddmigs.avg_user_impact AS INT) DESC;
Требуется дополнительная информация. Сколько еще столбцов в таблицах? Эти существующие таблицы с большим количеством запросов уже идут против них или все новые таблицы? Какие проблемы с производительностью вы наблюдаете, чтобы задать вопрос?
Я предполагаю, что все три столбца НЕ ПУСТО (не только для синтаксиса запроса, но и для полезности индекса).
Я бы начал с составного индекса для A.startDate + A.endDate и другого index на B.dates (но это, вероятно, не нужно). Если только эти даты не являются основной целью таблиц, я бы не стал создавать кластерные индексы для этих столбцов. Это верно вдвойне, если эти таблицы являются существующими таблицами, и к ним выполняются другие запросы. Предыдущие запросы могут быть написаны с ожиданием существующих кластерных индексов.
Я бы пошел с этим
CREATE CLUSTERED INDEX IX_DateRange ON dbo.A
(
StartDate,
EndDate DESC
)
GO
Я бы просто добавил кластерный индекс на B.dates. Если вы добавите индексы на startDate и endDate, он ничего не купит, потому что вы все равно получите сканирование индекса на A. Кластеризованный индекс на B дает вам поиск по индексу как минимум в B. Сканирование таблицы и сканирование индекса - это одно и то же, поэтому нет смысла добавлять индексы, чтобы исключить слово «сканирование таблицы» из вашего плана выполнения :)
Я бы смоделировал это несколькими способами или посмотрел, сможете ли вы повторить свой запрос чтобы не требовать сканирования таблицы на A, что, как я полагаю, на самом деле невозможно.
Если вам нужно оптимизировать, попробуйте запустить этот запрос в Query Analyzer.