Sqlserver
 sql >> Teknologi Basis Data >  >> RDS >> Sqlserver

Mengapa kueri T-SQL ke-2 berjalan jauh lebih cepat daripada yang pertama saat dipanggil oleh Reporting Services 2005 di aplikasi web

Anda mungkin menemukan kueri yang memiliki masalah dengan parameter sniffing, yang berkaitan dengan bagaimana Sql Server mencoba mengoptimalkan rencana eksekusi kueri Anda, tetapi dalam kasus ketika Layanan Pelaporan terlibat benar-benar mengacaukannya dan membuatnya berjalan sangat lambat.

Saya memiliki kasus dengan laporan yang memiliki dua kueri kompleks masing-masing sekitar 150 baris tetapi berjalan dalam 7 detik di lingkungan pengembangan saya - seluruh laporan membutuhkan waktu kurang dari 10 detik. Namun, ketika disebarkan ke server SSRS produksi, laporan membutuhkan waktu lebih dari 7 menit dan sering kali kehabisan waktu sehingga laporan tidak dapat dijalankan.

Sebagian besar informasi tentang masalah ini membicarakannya sehubungan dengan prosedur tersimpan. Jangan abaikan ini karena Anda tidak menggunakan prosedur tersimpan (seperti yang saya lakukan untuk waktu yang lama); itu sangat relevan dengan kueri Sql langsung juga.

Jadi perbedaan yang Anda lihat adalah bahwa Sql Server membuat dua rencana eksekusi yang sangat berbeda karena kedua kueri tersebut terstruktur secara berbeda.

Untungnya, solusinya sangat sederhana:masukkan parameter ke dalam variabel internal dan gunakan ini dalam kueri Anda. Saya melakukan ini dengan laporan saya dan laporan produksi kembali ke 10 detik seperti yang dilakukan versi pengembangan di Visual Studio.

Untuk melewati sniffing parameter untuk kueri pertama Anda, Anda akan membuatnya terlihat seperti ini:

BEGIN
    -- Use internal variables to solve parameter sniffing issues
    DECLARE @StartDateInternal AS DATETIME;
    DECLARE @EndDateInternal AS DATETIME;
    DECLARE @SchoolIDInternal AS INT;
    DECLARE @GradeLevelInternal AS INT;

    -- Copy the parameters into the internal variables
    SET @StartDateInternal = @StartDate;
    SET @EndDateInternal = @EndDate;
    SET @SchoolIDInternal = @SchoolID;
    SET @GradeLevelInternal = @GradeLevel;

    -- Now use the internal variables in your query rather than the parameters
    SELECT 
        c.TeacherID, u.FName + ' ' + u.lname as Teacher, count(sb.behaviorID) as BxCount, 
        sb.behaviorID, b.BehaviorName, std.GradeID, gl.GradeLevel
    FROM 
        StudentBehaviors sb
    join 
        Classes c on sb.classid = c.classid
    join 
        StudentDetails std on sb.studentID = std.StudentID and std.RecordIsActive=1
    join 
        users u on c.TeacherID = u.UserID
    join 
        Behaviors b on sb.behaviorID = b.BehaviorID
    join 
        GradeLevels gl on std.GradeID = gl.GradeLevelID
    WHERE 
        sb.classdate between @StartDateInternal and @EndDateInternal
        and c.schoolid = @SchoolIDInternal
        and std.GradeID = @GradeLevelInternal
    GROUP BY 
        c.TeacherID, sb.behaviorID, b.BehaviorName, u.lname, u.FName, 
        std.GradeID, gl.GradeLevel
    ORDER BY 
        u.LName, sb.behaviorID;

END;



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Menggunakan Penyimpanan Intel Optane untuk SQL Server

  2. Konversikan UTC Milidetik ke DATETIME di server SQL

  3. Kunci Utama Gabungan vs kolom ID tambahan?

  4. Ekspresi KASUS SQL Server

  5. Apa Perbedaan antara CHAR dan VARCHAR di SQL Server - Tutorial SQL Server / T-SQL Bagian 31