Группировка данных замедляет запрос, несмотря на уменьшение количества результатов на 25% - PullRequest
2 голосов
/ 20 марта 2012

У меня есть база данных Access из 4M строк, каждая из которых представляет отдельный заказ клиента.

Мне нужно выполнить запрос из Excel (я использую VBA), чтобы получить только заказы от клиентов в REGION1.

Я попробовал следующее (имена должны быть достаточно понятны):

Sub Query()

Dim cn As Object
Dim strFile As String
Dim strCon As String
Dim strSQL As String

strFile = "C:\Users\MyName\Desktop\DataBase.accdb"
strCon = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & strFile
Set cn = CreateObject("ADODB.Connection")
Set rs = CreateObject("ADODB.Recordset")
cn.Open strCon

strSQL = "SELECT [CUSTOMER], [DATE], [REVENUE]" _
& "FROM [SALES DB]" _
& "WHERE [REGION]='REGION1'"
rs.Open strSQL, cn, 0, 1

Worksheets(1).Cells(2, 1).CopyFromRecordset rs

rs.Close
Set rs = Nothing
cn.Close
Set cn = Nothing

End Sub

Это работает хорошо, но немного медленно, так как возвращает ~ 600 тыс. Строк.

Поэтому я подумал: «Кому нужен подробный список всех заказов клиентов? Мне просто нужен ежемесячный агрегат. Это должно уменьшить количество возвращаемых строк и, следовательно, повысить скорость!».

Поэтому я изменилсямой код:

strSQL = "SELECT [CUSTOMER], MONTH([DATE]), YEAR([DATE]), SUM([REVENUE])" _
& "FROM [SALES DB]" _
& "WHERE [REGION]='REGION1'"
& "GROUP BY [CUSTOMER], MONTH([DATE]), YEAR([DATE])"

Как я и ожидал, теперь отображаются результаты только ~ 450K.Дело в том, что запрос на самом деле стал медленнее.

На самом деле мне лучше извлечь несгруппированные данные, а затем агрегировать их с помощью простой сводной таблицы.

Как меньше данных можно извлечь медленнее?Я знаю, что между ними нужно выполнить некоторые вычисления, но все же.

Кто-нибудь знает, как мне решить эту проблему?

Ответы [ 2 ]

2 голосов
/ 20 марта 2012

Как вы и предполагали, базе данных приходится делать больше вычислений, в основном из-за вашей GROUP BY. Подумайте, что должно произойти в вашем втором запросе - базе данных нужно просмотреть все ~ 600 тыс. Строк, прежде чем можно будет вернуть первую строку, на тот случай, если в последней строке окажется самый ранний отсортированный клиент. Хотя, конечно, база данных может оптимизировать это с помощью индекса по клиенту. Однако вы также применяете функции MONTH и YEAR к полю и группируете их, поэтому база данных должна снова поработать с каждой строкой, прежде чем можно будет обработать первую строку для возврата.

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

Поскольку вы делаете это на одном рабочем столе, фактический объем данных, вероятно, не является определяющим фактором того, сколько времени это займет в целом. (Позднее редактирование) Извините, что может сбить с толку. Я имею в виду, что общий объем данных, перемещаемых между базой данных и таблицей Excel, не является основным определяющим фактором - разница между перемещением 600 тыс. И 450 тыс. Не будет такой большой. Основным определяющим фактором является то, сколько решений работа базы данных должна сделать. Однако если вы передаете данные по сети (например, из базы данных центрального сервера sql), то объем передаваемых данных станет большим фактором общего времени.

1 голос
/ 21 марта 2012

Вы не упоминаете фактическое время, затраченное на запросы, но вот несколько мыслей:

  1. Убедитесь, что у вас есть индексы для всех полей в базе данных, которую вы группируете или фильтруете.

  2. Если вы являетесь единственным пользователем этой базы данных, откройте ее в эксклюзивном режиме:
    Для ADO используйте строку подключения:

    "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & strFile & ";Mode=12;"
    
  3. Используйте DAO вместо ADO.
    DAO является родным для Access и, как правило, быстрее.

    Прежде всего, добавьте ссылку на Access Engine в Excel:

    • В среде IDE в разделе «Инструменты»> «Ссылки» перейдите в список и проверьте:
      Microsoft Office 12.0 Access database engine Object Library.

    • Если у вас есть Access 2010, ссылка будет:
      Microsoft Office 14.0 Access database engine Object Library.

    • В более старых версиях Access (2003 и более ранних), использующих вместо этого движок Jet (только файлы MDB), это будет:
      Microsoft DAO 3.6 Object Library.

    Затем используйте приведенный ниже код VBA для загрузки данных в свой рабочий лист:

    Public Sub LoadFromDb()
        Dim db As DAO.Database
        Dim rs As DAO.Recordset
        ' Open the database in Exclusive mode '
        Set db = DBEngine.OpenDatabase("C:\Users\MyName\Desktop\DataBase.accdb", True)
        ' Open the recordset as a snapshot, it's faster than the default dbDynaset '
        Set rs = db.OpenRecordset("SELECT CUSTOMER, DATE, REVENUE " & _
                "FROM [SALES DB] WHERE REGION='REGION1'", dbOpenSnapshot)
        ' Copy the recordset to the sheet '
        Worksheets(1).Cells(2, 1).CopyFromRecordset rs
        rs.Close
        db.Close
        Set rs = Nothing
        Set db = Nothing
    End Sub
  1. Если вы в основном импортируете свои данные из Access, чтобы отобразить их в сводной таблице, возможно, вам лучше обслуживать сводную таблицу в самом Access.

  2. По этому вопросу знаете ли вы, что вы можете разделить свою базу данных для совместного использования базы данных и использовать бесплатную Access Runtime , чтобы все пользователи могли просматривать ваши отчеты и играть с данными на их машине?

  3. Переход на SQL Server или другую базу данных может / не может решить ваши проблемы вообще:

    • если на вашем компьютере установлен SQL Server, для расчета вашего запроса потребуется более или менее много ресурсов, как если бы база данных MS Access была на вашем компьютере.

    • , если SQL Server находится на удаленной машине, большую часть времени будет уделяться передаче сетевых данных.

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

  4. Если у вас есть так много данных, чтобы просеять, Excel, вероятно, не лучший инструмент для работы, и вам может быть лучше обслуживать специальное приложение для отчетности или Business Intelligence.
    Существует множество OpenSource и коммерческих платформ, например:

...