2010-08-13 3 views
0

Я знаю, что все функции агрегирования домена медленны, но я ищу наименьшее из зла.MS Access выполняет dlookup по запросу или dsum?

Какой из следующих двух вариантов будет быстрее?

  1. Создайте запрос, который будет группироваться по уникальному значению и суммировать общее количество. Попросите dlookup получить мою сумму из запроса.
  2. Сделайте dsum на главной таблице, критерии которой совпадают с моими столбцами GROUP BY в опции 1?

Edit 1
Мой вопрос общий вопрос, который я задавался вопросом во многих ситуациях, но ниже конкретной ситуации при рассмотрении прямо сейчас.

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

=DLookUp("[SumOfPrice]","tm_materialsUsedByPart","[Part]=" & [cmbPart]) 

tm_materialsUsedByPart в настоящее время является запрос, суммируя все используемые материалы.

Быстрее ли использовать dsum, которые имеют те же критерии или быстрее выполнить запрос, а затем взять одну строку, соответствующую моим критериям?

+0

Пример добавлен .. – Icode4food

ответ

1
=DLookUp("[SumOfPrice]","tm_materialsUsedByPart","[Part]=" & [cmbPart]) 

Не видя SQL для tm_materialsUsedByPart, мы можем только догадываться, что он делает. Возможно, он читает целую таблицу или набор таблиц JOINed и использует GROUP BY для агрегирования суммы (цены) в качестве SumOfPrice.

Он должен быть быстрее DSum против базовой таблицы, особенно если поле [Part] проиндексировано.

=DSum("[Price]", "tblRowSource", "[Part]=" & Me.cmbPart) 

Таким образом, вы запрашиваете механизм базы данных только для чтения строк, содержащих требуемое значение [Part]. В вашем материалеUsedByPart запрос требует чтения всех строк, затем вы извлекаете одно значение группы, которое вы хотите. Не делай этого. Попросите механизм базы данных прочитать наименьшее количество строк, чтобы получить необходимую вам информацию.

Редактировать: Я ошибался, что DSum против базовой таблицы будет быстрее DLookup против совокупного запроса. Как предложил @Thomas, в моем простом тесте план запросов одинаковый для обоих случаев.

Вот мой запрос, qryMinutesPerClient:

SELECT Time_Sub.CLIENT_ID, Sum(Time_Sub.MINUTES) AS SumOfMINUTES 
FROM Time_Sub 
GROUP BY Time_Sub.CLIENT_ID; 

Тогда

DLookup("SumOfMINUTES","qryMinutesPerClient","CLIENT_ID = 11111") 

результаты в этом плане запроса:

- Inputs to Query - 
Table 'Time_Sub' 
- End inputs to Query - 

01) Restrict rows of table Time_Sub 
     using rushmore 
     for expression "Time_Sub.CLIENT_ID=11111" 
02) Group result of '01)' 

И с

DSum("MINUTES","Time_Sub","CLIENT_ID = 11111") 

план тот же:

- Inputs to Query - 
Table 'Time_Sub' 
- End inputs to Query - 

01) Restrict rows of table Time_Sub 
     using rushmore 
     for expression "CLIENT_ID=11111" 
02) Group result of '01)' 

Самым важным вопросом производительности включает в себя «используя Рашмор», что возможно, потому что мое поле CLIENT_ID индексируется. Без этого индекса Rushmore не может использоваться в плане запроса, а подходы DLookup и DSum равны заметно медленнее, чем у Rushmore.

+0

Итак, MS Access недостаточно умен, чтобы использовать индекс, даже так, как я это делаю сейчас? [Часть] индексируется. Кроме того, у вас был хороший момент о том, что делает запрос 'tm_materialsUsedByPart', он делает один JOIN. – Icode4food

+1

Мне нравится предложение @Thomas, чтобы включить итоговые данные в источник записи формы, и это то, что я сделал бы, пока источник записи может быть доступен только для чтения. Если вам нужно отредактировать значения источника записи в вашей подчиненной форме ввода времени, используйте DSum(). – HansUp

+0

Доступ не делает ничего. Но движок базы данных Jet/ACE. Вы можете Google SHOWPLAN, если хотите узнать, как он оптимизирует запросы, но это не поможет выяснить, как работают функции агрегации домена. В общем, Jet/ACE (и функции агрегации домена) будут использовать все индексы с несколькими исключениями (например, НЕ используются с подзапросами, где иногда он использует индекс только на одной стороне сравнения). –

1

Есть еще два варианта: коррелированный подзапрос или производная таблица. Связанный подзапрос повлечет за собой объявляя столбец в запросе себе быть запрос:

Select ... 
, (Select Sum(Foo) 
    From Bar 
    Where Bar.FK = Gamma.PK) As Total 
From Gamma 

Производная таблица, в Access, будет включать в себя создание сохраненный запрос, который делает все суммы, а затем подключиться к этому запрос в ваш главный запрос. Хотя в основном запросе можно построить запрос итогов «на лету», мой опыт в том, что Access более счастлив с сохраненным запросом и стандартным соединением. Если вы покажете нам больше о том, чего вы пытаетесь достичь, вы можете получить более конкретные ответы.

EDIT

IMO, самое быстрое решение будет включать в общей сложности, с помощью сохраненного запроса в источнике для формы. I.e., не использовать ни DLookup, ни DSum, но вместо этого включить общее количество в качестве части RecordSource формы, присоединившись к запросу, который вычисляет общее количество.

Во-вторых, чтобы узнать, какая функция будет работать лучше всего, вам нужно будет провести некоторые тесты производительности против ваших данных. Я предполагаю, что производительность будет сопоставима между этими двумя. Даже с DLookup против хранимого запроса Access должен быть достаточно умным, чтобы вводить критерии фильтрации и фактически получать сопоставимый план выполнения с использованием DSum.

Наконец, если вы собираетесь использовать функцию агрегирования домена, и единственная цель запроса, используемого в DLookup, состоит в том, чтобы обслуживать итоговые значения для этой формы, то IMO, имеет смысл использовать DSum, поскольку это делает ваше намерение использование функции агрегирования домена более ясное для читателя.

+0

Я добавил править 1. Надеюсь, это сделает более ясным то, что я прошу. – Icode4food

+0

Я не могу добавить поле в источник записей формы, потому что данные формы должны быть доступны для редактирования. Наличие запроса GROUP BY в источнике записей не позволит редактировать данные. – Icode4food

+1

@jeffreymb - вам не нужна группа в источнике записи. Если вы используете сохраненный запрос, только сохраненный запрос будет иметь группу. Основной запрос не будет. Если вы используете коррелированный подзапрос в источнике записи, он будет иметь только группу, а не основной запрос. – Thomas

Смежные вопросы