Медленный SQL-код на локальном сервере в MS Access - PullRequest
2 голосов
/ 11 ноября 2008

У меня есть конкретный оператор SQL, выполнение которого занимает около 30 секунд, и мне интересно, может ли кто-нибудь увидеть проблему с ним или где мне нужна дополнительная индексация.

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

Спасибо

PG

SELECT TabDrawer.DrawerName, TabDrawer.DrawerSortCode, TabDrawer.DrawerAccountNo, TabDrawer.DrawerPostCode, QryAllTransactons.TPCChequeNumber, tabdrawer.drawerref
FROM TabDrawer LEFT JOIN QryAllTransactons ON  TabDrawer.DrawerRef=QryAllTransactons.tpcdrawer
WHERE (Forms!FrmSearchCompany!SearchName Is Null 
      Or [drawername] Like Forms!FrmSearchCompany!SearchName & "*") 
      And (Forms!FrmSearchCompany.SearchPostcode Is Null 
      Or [Drawerpostcode] Like Forms!FrmSearchCompany!Searchpostcode & "*") 
      And (Forms!FrmSearchCompany!SearchSortCode Is Null 
      Or [drawersortcode] Like Forms!FrmSearchCompany!Searchsortcode & "*") 
      And (Forms!FrmSearchCompany!Searchaccount Is Null 
      Or [draweraccountno] Like Forms!FrmSearchCompany!Searchaccount & "*") 
      And (Forms!FrmSearchCompany!Searchcheque Is Null 
      Or [tpcchequenumber] Like Forms!FrmSearchCompany!Searchcheque & "*");
    ");

EDIT

Кажется, что Hold находится в запросе объединения, который формирует запрос QryAllTransactons.

SELECT 
  "TPC" AS Type, 
  TabTPC.TPCRef, 
  TabTPC.TPCBranch, 
  TabTPC.TPCDate, 
  TabTPC.TPCChequeNumber, 
  TabTPC.TPCChequeValue, 
  TabTPC.TPCFee, 
  TabTPC.TPCAction,
  TabTPC.TPCMember, 
  tabtpc.tpcdrawer,
  TabTPC.TPCUser,
  TabTPC.TPCDiscount,
  tabcustomers.*
FROM 
  TabTPC 
  INNER JOIN TabCustomers ON TabTPC.TPCMember = TabCustomers.CustomerID

UNION ALL 

SELECT 
 "CTP" AS Type, 
  TabCTP.CTPRef, 
  TabCTP.CTPBranch, 
  TabCTP.CTPDate, 
  TabCTP.CTPChequeNumb, 
  TabCTP.CTPAmount, 
  TabCTP.CTPFee, 
  TabCTP.CTPAction,
  TabCTP.CTPMember,
  0 as CTPXXX,
  TabCTP.CTPUser,
  TabCTP.CTPDiscount, 
  TABCUSTOMERS.*
FROM 
  TabCTP  
  INNER JOIN TabCustomers ON Tabctp.ctpMember = TabCustomers.CustomerID;

Я проделал немалую работу с простыми объединенными запросами, но никогда раньше такого не было ...

Ответы [ 6 ]

2 голосов
/ 12 ноября 2008

Две вещи. Поскольку это база данных Access с бэкэндом SQL Server, вы можете значительно повысить скорость, преобразовав ее в сохраненный процесс.

Во-вторых, вам действительно нужно возвращать все эти поля, особенно в таблице tabCustomers? Никогда не возвращайте больше полей, чем вы на самом деле намереваетесь использовать, и вы улучшите производительность.

1 голос
/ 11 ноября 2008

Сначала попробуйте сжать и восстановить файл .mdb.

Затем упростите предложение WHERE:

WHERE
  [drawername] Like Nz(Forms!FrmSearchCompany!SearchName, "") & "*"
  And 
  [Drawerpostcode] Like Nz(Forms!FrmSearchCompany!Searchpostcode, "") & "*"
  And 
  [drawersortcode] Like Nz(Forms!FrmSearchCompany!Searchsortcode, "") & "*"
  And 
  [draweraccountno] Like Nz(Forms!FrmSearchCompany!Searchaccount, "") & "*"
  And 
  [tpcchequenumber] Like Nz(Forms!FrmSearchCompany!Searchcheque, "") & "*"

Он все еще работает медленно?

EDIT

Как выяснилось, вопрос не был ясен в том, что это расширенная база данных Access с серверной частью SQL Server и интерфейсом Access Project.

Это проливает новый свет на всю проблему.

Можете ли вы объяснить более подробно как весь этот запрос предназначен для использования?

Если вы используете его для заполнения RecordSource какой-либо Формы или Отчета, я думаю, что вы сможете реорганизовать все это так:

  • просмотр SQL-сервера, который возвращает правильные данные
  • запрашивать это представление с синтаксисом сервера SQL, а не с синтаксисом Access
  • пусть сервер разберется
0 голосов
/ 20 ноября 2008

Когда вы увеличили размер, вы убедились, что таблицы были правильно проиндексированы? При правильном использовании индексы значительно ускоряют запросы (обратите внимание, что они также могут замедлять вставки / обновления / удаления, поэтому тщательно выбирайте, что индексировать)

0 голосов
/ 11 ноября 2008

Избавьтесь от подобных операторов.

В вашем случае они вам не нужны. Просто проверьте, начинается ли поле с заданного значения, которое вы можете получить примерно так:

Left([field], Len(value)) = value

Этот метод, примененный к вашему запросу, выглядел бы так (сделал некоторое переформатирование для лучшей читаемости):

SELECT
  TabDrawer.DrawerName, 
  TabDrawer.DrawerSortCode, 
  TabDrawer.DrawerAccountNo, 
  TabDrawer.DrawerPostCode, 
  QryAllTransactons.TPCChequeNumber, 
  TabDrawer.DrawerRef
FROM
  TabDrawer 
  LEFT JOIN QryAllTransactons 
    ON TabDrawer.DrawerRef = QryAllTransactons.TpcDrawer
WHERE 
  (Forms!FrmSearchCompany!SearchName Is Null 
  Or Left([drawername], Len(Forms!FrmSearchCompany!SearchName)) = Forms!FrmSearchCompany!SearchName)
And
  (Forms!FrmSearchCompany.SearchPostcode Is Null 
  Or Left([Drawerpostcode], Len(Forms!FrmSearchCompany!Searchpostcode)) = Forms!FrmSearchCompany!Searchpostcode) 
And 
  (Forms!FrmSearchCompany!SearchSortCode Is Null 
  Or Left([drawersortcode], Len(Forms!FrmSearchCompany!Searchsortcode)) = Forms!FrmSearchCompany!Searchsortcode) 
And 
  (Forms!FrmSearchCompany!Searchaccount Is Null 
  Or Left([draweraccountno], Len(Forms!FrmSearchCompany!Searchaccount)) = Forms!FrmSearchCompany!Searchaccount) 
And 
  (Forms!FrmSearchCompany!Searchcheque Is Null 
  Or Left([tpcchequenumber], Len(Forms!FrmSearchCompany!Searchcheque)) = Forms!FrmSearchCompany!Searchcheque)

Обратите внимание, что вы сравниваете регистр символов. Я не совсем уверен, является ли оператор like в MS-Access нечувствительным к регистру. При необходимости преобразуйте обе строки в верхний или нижний регистр.

0 голосов
/ 11 ноября 2008

Вы пробовали запустить каждый из подзапросов в союзе? Обычно оптимизаторы не тратят много времени на проверку эффективности между элементами объединения - каждый из них работает по-своему.

Учитывая этот факт, вы также можете поместить логику "IF" в процедурный код и запускать каждый из тестов в некотором вероятном порядке обнаружения, без значительных дополнительных затрат на дополнительные вызовы.

0 голосов
/ 11 ноября 2008

Сколько строк в QryAllTransactons?

Если ваш результат возвращает 0 строк, то Access может увидеть это сразу и остановить, но если он возвращает хотя бы одну строку, ему нужно получить весь набор результатов QryAllTransactons, чтобы он мог выполнить объединение внутри. Это было бы мое первое предположение о том, что происходит.

Лучше всего ставить соединения на SQL Server. Попробуйте создать представление, которое выполняет LEFT OUTER JOIN, и запросите его.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...