Skip to main content

MS SQL Server: Query store fix performance issue

Here are some reference links and script I used to fix performance issue by force query plan using query store feature:

 --https://docs.microsoft.com/en-us/sql/relational-databases/performance/monitoring-performance-by-using-the-query-store?view=sql-server-ver16

--https://www.sqlshack.com/force-query-execution-plan-using-sql-server-2016-query-store/

--ALTER DATABASE [system-abccompany] SET QUERY_STORE = ON (OPERATION_MODE = READ_WRITE);

--ALTER DATABASE [system-abccompany] SET QUERY_STORE = ON ( WAIT_STATS_CAPTURE_MODE = ON );

--SELECT actual_state_desc, desired_state_desc, current_storage_size_mb,    max_storage_size_mb, readonly_reason, interval_length_minutes,    stale_query_threshold_days, size_based_cleanup_mode_desc,    query_capture_mode_desc

--FROM sys.database_query_store_options;

--select count(*) from sys.query_store_query

--ALTER DATABASE [system-abccompany] SET QUERY_STORE (MAX_STORAGE_SIZE_MB =100);

--ALTER DATABASE [system-abccompany] SET QUERY_STORE CLEAR;

--ALTER DATABASE [system-abccompany] SET QUERY_STORE (OPERATION_MODE = READ_WRITE);

--ALTER DATABASE [system-abccompany]  SET QUERY_STORE (OPERATION_MODE = READ_ONLY);


/*check forced plan query

use [system-abccompany]

go

SELECT p.plan_id, p.query_id, q.object_id as containing_object_id,

    force_failure_count, last_force_failure_reason_desc,p.query_plan,p.*

FROM sys.query_store_plan AS p

JOIN sys.query_store_query AS q on p.query_id = q.query_id

WHERE is_forced_plan = 1;

*/

/* find out if the query is captured.

SELECT Txt.query_text_id, Txt.query_sql_text, Pl.plan_id, Qry.*

FROM sys.query_store_plan AS Pl

INNER JOIN sys.query_store_query AS Qry

    ON Pl.query_id = Qry.query_id

INNER JOIN sys.query_store_query_text AS Txt

    ON Qry.query_text_id = Txt.query_text_id

where Txt.query_sql_text like '%SELECT * FROM (SELECT  tblAssignmentStatus%'

*/


-- get the query_id and the good plan_id  which last_duration is good

SELECT qsp.query_id, QSP.plan_id,  QST.query_sql_text, qsq.query_hash, qsp.query_plan_hash, QSRS.last_duration,

QSRS.avg_duration, qsp.query_plan, QSQ.last_execution_time,  -- timezone is not right, show 7 hours ahead, also sometimes it's even less than the first_execution_time

QSRS.first_execution_time,  -- timezone is not right, show 7 hours ahead

QSRS.avg_logical_io_reads,QSRS.avg_logical_io_writes 

FROM sys.query_store_plan AS QSP  JOIN sys.query_store_query AS QSQ      ON QSP.query_id = QSQ.query_id  

JOIN sys.query_store_query_text AS QST      ON QSQ.query_text_id = QST.query_text_id 

JOIN sys.query_store_runtime_stats  QSRS   ON QSP.plan_id =QSRS.plan_id

where QST.query_sql_text like '%SELECT%tblAssignmentStatuses%AssignmentStatusesID%AS%'

order by QSQ.last_execution_time desc


--EXEC sp_query_store_force_plan @query_id = 125, @plan_id = 128


/* is there a forced plan?

SELECT p.query_id

FROM sys.query_store_plan AS p

JOIN sys.query_store_query AS q on p.query_id = q.query_id

WHERE is_forced_plan = 1;

*/

-- stop the plan capture after the good plan is caught.

ALTER DATABASE [system-abccompany]  SET QUERY_STORE (OPERATION_MODE = READ_ONLY);

/*remove redundant query id from query store, method 1, there are still some leftover in query_store_query, you can use method 2 below to remove

DECLARE @id int;

DECLARE adhoc_queries_cursor CURSOR

FOR

    SELECT q.query_id

    FROM sys.query_store_query_text AS qt

    JOIN sys.query_store_query AS q

    ON q.query_text_id = qt.query_text_id

    JOIN sys.query_store_plan AS p

    ON p.query_id = q.query_id

    JOIN sys.query_store_runtime_stats AS rs

    ON rs.plan_id = p.plan_id

    WHERE is_forced_plan <> 1

    ORDER BY q.query_id;

OPEN adhoc_queries_cursor ;

FETCH NEXT FROM adhoc_queries_cursor INTO @id;

WHILE @@fetch_status = 0

BEGIN

    PRINT 'EXEC sp_query_store_remove_query ' + str(@id);

    EXEC sp_query_store_remove_query @id;

    FETCH NEXT FROM adhoc_queries_cursor INTO @id;

END

CLOSE adhoc_queries_cursor;

DEALLOCATE adhoc_queries_cursor;

*/



/*remove redundant query id from query store. method 2, it will delete any query_id that's not using force plan.

DECLARE @id int;

DECLARE adhoc_queries_cursor CURSOR

FOR

    SELECT q.query_id from sys.query_store_query AS q

     WHERE query_id not in

(

SELECT p.query_id

FROM sys.query_store_plan AS p

JOIN sys.query_store_query AS q on p.query_id = q.query_id

WHERE is_forced_plan = 1

)

    ORDER BY q.query_id;

OPEN adhoc_queries_cursor ;

FETCH NEXT FROM adhoc_queries_cursor INTO @id;

WHILE @@fetch_status = 0

BEGIN

    PRINT 'EXEC sp_query_store_remove_query ' + str(@id);

    EXEC sp_query_store_remove_query @id;

    FETCH NEXT FROM adhoc_queries_cursor INTO @id;

END

CLOSE adhoc_queries_cursor;

DEALLOCATE adhoc_queries_cursor;

*/

Comments

Popular posts from this blog

non-existent process lock port on windows server

I have a database link created between oracle and sqlserver using oracle tg4odbc, the product is installed on windows server and run as service "OracleOraGtw11g_home1TNSListener", but sometime the service cannot started, the root cause of this problem is that the port number 1521 is used by an non-existent process. The first step is to use netstat -bano|find "1521" to get the process id, in my case it's 5844, which shows the connection is from my oracle server 10.8.0.169 H:\>netstat -bano|find "1521"   TCP    0.0.0.0:1521           0.0.0.0:0              LISTENING       5844   TCP    10.14.45.33:1521       10.8.0.169:42987       ESTABLISHED     5844 however the process id does not show in either task manager or process explorer. The next step is to run tcpview, which shows non-existent under process column, there are three rows, two show status as "listening", the other one shows status "established", right click and k

Opatch apply/lsinventory error: oneoff is corrupted or does not exist

I am applying the quarterly patch for 19c RDBMS, I tried using napply but failed, but somehow it corrupted the inventory though nothing applied. further apply and lsinventory command ran into error like this: $ ./OPatch/opatch lsinventory Oracle Interim Patch Installer version 12.2.0.1.21 Copyright (c) 2020, Oracle Corporation.  All rights reserved. Oracle Home       : /u02/app/oracle/19.0.0 Central Inventory : /u01/app/oraInventory    from           : /u02/app/oracle/19.0.0/oraInst.loc OPatch version    : 12.2.0.1.21 OUI version       : 12.2.0.7.0 Log file location : /u02/app/oracle/19.0.0/cfgtoollogs/opatch/opatch2020-09-08_13-35-59PM_1.log Lsinventory Output file location : /u02/app/oracle/19.0.0/cfgtoollogs/opatch/lsinv/lsinventory2020-09-08_13-35-59PM.txt -------------------------------------------------------------------------------- Inventory load failed... OPatch cannot load inventory for the given Oracle Home. LsInventorySession failed: Unable to create patchObject Possible ca

shell script to clean up oracle dumpfile

https://github.com/iacosta/personal/blob/master/shells/cleanhouse.sh #!/bin/ksh # # Script used to cleanup any Oracle environment. # # Cleans:      audit_file_dest #              background_dump_dest #              core_dump_dest #              user_dump_dest #              Clusterware logs # # Rotates:     Alert Logs #              Listener Logs # # Scheduling:  00 00 * * * /networkdrive/dba/scripts/purge/cleanup.sh -d 7 > /u01/dba/bin/cleanup.log 2>&1 # # Created By:  Lei Dao # # # RM="rm -f" RMDIR="rm -rf" LS="ls -l" MV="mv" TOUCH="touch" TESTTOUCH="echo touch" TESTMV="echo mv" TESTRM=$LS TESTRMDIR=$LS SUCCESS=0 FAILURE=1 TEST=0 HOSTNAME=`hostname` ORAENV="oraenv" TODAY=`date +%Y%m%d` ORIGPATH=/usr/local/bin:$PATH ORIGLD=$LD_LIBRARY_PATH export PATH=$ORIGPATH # Usage function. f_usage(){   echo "Usage: `basename $0` -d DAYS [-a DAYS] [-b DAYS] [