Скорость запроса SQL Access

У меня есть следующий запрос в моей базе данных Access 2003:

SELECT 
    Projet.OTP AS OTP, 
    NumeroDA, 
    SUM(Quantite*PrixReelCommande) AS PrixTotal, 
    FIRST(Fournisseur1) AS Fournisseur, 
    FIRST(Projet.NumeroCommandeReservation) AS NumeroCommande, 
    FIRST(Projet.GestionContrat) AS GestionContrat, 
    FIRST(Projet.Acheteur) AS Acheteur, 
    MIN(DateLivraisonContractuelle) AS DateLivraisonContrat, 
    MAX(DateFournisseurLivraison) AS DateLivraisonFournisseur, 
    FIRST(InfoProjet.NomInstallation) AS NomInstallation, 
    FIRST(InfoProjet.TitreMandat) AS TitreMandat
FROM Projet LEFT JOIN InfoProjet ON Projet.OTP=InfoProjet.OTP
WHERE NumeroDA Like "#*" And NumeroDA IN (
                                            SELECT NumeroDA FROM Projet 
                                            WHERE NumeroCommandeReservation="" Or NumeroCommandeReservation Is Null Or NumeroCommandeReservation="0"
                                        )
GROUP BY Projet.OTP, Projet.NumeroDA
ORDER BY Projet.OTP, Projet.NumeroDA

В таблице Projet около 2500 строк, а в InfoProjet всего 200 строк. Открытие любой из этих таблиц в Access занимает менее 1 секунды. Однако выполнение вышеуказанного запроса занимает более 5 секунд.

Я хотел бы знать, могу ли я что-нибудь сделать, чтобы улучшить производительность этого запроса. Есть ли в запросе что-то, чего мне следует избегать с точки зрения производительности? Или у меня просто ограничения доступа? Я предполагаю, что использование Like в подзапросе не помогает, но должно быть что-то еще, что замедляет запрос.


person dan    schedule 25.03.2013    source источник
comment
У вас есть индекс [OTP] в обеих таблицах? Если да, включает ли индекс столбец NumeroDA. У вас есть индекс по NumeroCommandeReservation, а также включаете NumeroDA?   -  person ljh    schedule 25.03.2013
comment
Нет индекса OTP, есть несколько строк с одинаковыми OTP. Но мы можем установить неуникальный индекс в Access, как вы думаете, это поможет в этом случае? То же самое и для NumeroDA, есть несколько строк с одним и тем же NumeraDA и NumeroCommandeReservation. ПК — это NumeroListe и NumeroArticle, оба проиндексированы с поддержкой дубликатов.   -  person dan    schedule 25.03.2013
comment
Он не обязательно должен быть уникальным, неуникальный индекс также может помочь в запросе, если вы можете создать составной индекс или покрывающий индекс, который может помочь вам больше.   -  person ljh    schedule 25.03.2013


Ответы (2)


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

SELECT 
    Projet.OTP AS OTP, 
    NumeroDA, 
    SUM(Quantite*PrixReelCommande) AS PrixTotal, 
    FIRST(Fournisseur1) AS Fournisseur, 
    FIRST(Projet.NumeroCommandeReservation) AS NumeroCommande, 
    FIRST(Projet.GestionContrat) AS GestionContrat, 
    FIRST(Projet.Acheteur) AS Acheteur, 
    MIN(DateLivraisonContractuelle) AS DateLivraisonContrat, 
    MAX(DateFournisseurLivraison) AS DateLivraisonFournisseur, 
    FIRST(InfoProjet.NomInstallation) AS NomInstallation, 
    FIRST(InfoProjet.TitreMandat) AS TitreMandat
FROM Projet LEFT JOIN InfoProjet ON Projet.OTP=InfoProjet.OTP
WHERE NumeroDA Like "#*" And (
     NumeroCommandeReservation="" Or 
     NumeroCommandeReservation Is Null Or 
     NumeroCommandeReservation="0")

GROUP BY Projet.OTP, Projet.NumeroDA
ORDER BY Projet.OTP, Projet.NumeroDA
person PowerUser    schedule 25.03.2013
comment
Это работает и дает мне тот же результат менее чем за секунду. Итак, проблема заключается в подзапросе с функцией IN(). Похоже, Access это не нравится. Я приму ваш ответ, так как он решит мою проблему, теперь я буду более осторожен с этим. Этот запрос, вероятно, еще можно улучшить. - person dan; 25.03.2013
comment
В интересах улучшения запроса эти операторы First() заставляют меня немного нервничать. Они могли скрывать что-то важное. Я рекомендую избавиться от этих операторов First() и вместо этого поместить эти поля в оператор Group By. Есть смысл? - person PowerUser; 26.03.2013

Попробуйте запустить это и посмотрите, сколько строк он возвращает:

SELECT COUNT(*)
FROM Projet LEFT JOIN InfoProjet ON Projet.OTP=InfoProjet.OTP
WHERE NumeroDA Like "#*" And NumeroDA IN (
                                        SELECT NumeroDA FROM Projet 
                                        WHERE NumeroCommandeReservation="" 
                                        Or NumeroCommandeReservation Is Null 
                                        Or NumeroCommandeReservation="0"
                                    )

Причина: объединение может возвращать больше строк, чем вы ожидаете, но, поскольку у вас есть только MAX/MIN/FIRST агрегатов, вы можете этого не заметить.

person bendataclear    schedule 25.03.2013
comment
Исходный запрос возвращает только 23 строки, и это нормально. Я только что попробовал ваш запрос, который такой же длинный, как и мой исходный запрос, и он возвращает число 111. - person dan; 25.03.2013
comment
@dnLL в этом случае, я думаю, единственное, что поможет, — это добавить индексы, как предложил ljh, или переписать запрос, чтобы удалить подзапрос и переместить его в соединение или раздел where. - person bendataclear; 25.03.2013
comment
Решение PowerUser фактически решило мою проблему, но я также рассмотрю возможность добавления индексов. - person dan; 25.03.2013