TASK in Snowflake not running - snowflake-cloud-data-platform

I have a task on Snowflake which if I resume,it runs, but I don't see any history in the next day. I have scheduled it to run every min.
Do they have a timelimit?
Create statement :
create or replace task TEMP_DB.IAM.IAM_TASK
warehouse= ELT_WHS
schedule='1 minute'
as call TEMP_DATA();
ALTER TASK TEMP_DB.IAM.IAM_TASK RESUME;
to see history I am using the following statement:
select *
from table(information_schema.task_history())
where
database_name = 'TEMP_DB'
order by scheduled_time desc;

The default result limit is 100, and it may reduce the number of rows returned. The database_name filter is applied afterwards.
I would try to extend the limit:
select *
from table(information_schema.task_history(RESULT_LIMIT => 10000))
where database_name = 'TEMP_DB'
order by scheduled_time desc;
or try to search by task name:
select *
from table(information_schema.task_history(TASK_NAME => 'IAM_TASK'))
where database_name = 'TEMP_DB'
order by scheduled_time desc;
Alternatively TASK_HISTORY view could be used:
Latency for the view may be up to 45 minutes.
SELECT *
FROM snowflake.account_usage.task_history
WHERE DATABASE_NAME = 'TEMP_DB'
AND SCHEMA_NAME = 'IAM'
AND NAME = 'IAM_TASK'
ORDER BY SCHEDULED_TIME DESC;

Related

Change the intervals of records registered by sys.dm_os_ring_buffers?

I want to get the current CPU percentage that is shown in the task manager, I found this query in This Question that gives the total CPU usage which is what I want
Query:
SELECT #ts_now = cpu_ticks / CONVERT(FLOAT, ms_ticks) FROM sys.dm_os_sys_info
SELECT top 30 record_id,
DATEADD(ms, -1 * (#ts_now - [timestamp]), GETDATE()) AS EventTime,
SQLProcessUtilization,
SystemIdle,
100 - SystemIdle - SQLProcessUtilization AS OtherProcessUtilization,
100 - SystemIdle AS TotalCPU
FROM (
SELECT
record.value('(./Record/#id)[1]', 'int') AS record_id,
record.value('(./Record/SchedulerMonitorEvent/SystemHealth/SystemIdle)[1]', 'int') AS SystemIdle,
record.value('(./Record/SchedulerMonitorEvent/SystemHealth/ProcessUtilization)[1]', 'int') AS SQLProcessUtilization,
TIMESTAMP
FROM (
SELECT TIMESTAMP, CONVERT(XML, record) AS record
FROM sys.dm_os_ring_buffers
WHERE ring_buffer_type = N'RING_BUFFER_SCHEDULER_MONITOR'
AND record LIKE '% %') AS x
) AS y
ORDER BY record_id DESC
Output:
The problem is that this only refreshes every minute, and I need the current CPU when the query is executed. Is there a way to change the interval of the records that are generated? If not could I trigger a new record or another approach?
You can get an instantaneous value for CPU utilization from DMV that exposes the raw performance counter data. Note that since the perf counters are raw here, you have to perform either sampling or calculation based on the performance counter type.
EG:
select 100.* c.cntr_value / base.cntr_value cpu_usage_percentage
from sys.dm_os_performance_counters c
join sys.dm_os_performance_counters base
on c.object_name = base.object_name
and c.instance_name = base.instance_name
where c.counter_name = 'CPU usage %'
and base.counter_name = 'CPU usage % base'
and c.object_name = 'SQLServer:Resource Pool Stats'
and c.instance_name = 'default'

MS SQL If Selected is NULL Run another statement

I have two sql statements,
select * from UserTable where role='HOD'
select * from UserTable where role='Supervisor'
I want the results to be in a way such that if the first statement returns nothing, I want the second statement to run and if first statement returns something, second statement do not need to run. Is there a way to do it, be it in a stored procedure or a SQLQuery?
Executing two queries is more expensive than executing a single one that returns both result sets. It would be cheaper to filter the results on the client.
Even if you return all results in a single query, you can differentiate the two cases. For example, HOD always comes before Supervisor. You could use a ranking function like ROW_NUMBER() to assign a value to each row, depending on whether it matches HOD or Supervisor:
with a as (
select * ,row_number() over (partition by Role order by Role) as rn
from UserTable
where Role in ('HOD','Supervisor')
)
select *
from a
where rn=1
Another option is to combine a query that returns HOD with a query that returns Supervisor if HOD doesn't exist:
select *
from UserTable
where Role ='HOD'
UNION ALL
select *
from UserTable
where Role ='Supervisor'
AND NOT EXISTS (SELECT 1
from UserTable
where Role ='Supervisor')
The performance of both queries can be improved if Role is part of an index. The first query becomes equivalent to a simple index seek if the table has an index that covers all the returned fields. If the query returns only eg, ID, UserName, Role :
with a as (
select * ,row_number() over (partition by Role order by Role) as rn
from UserTable
where Role in ('HOD','Supervisor')
)
select ID,UserName, Role
from a
where rn=1
and the table has a covering index:
CREATE INDEX IX_UserTable_Roles ON UserTable (Role,ID,UserName)
The resulting execution plan is a single INDEX SEEK on the index
Try This
IF EXISTS (
SELECT 1 FROM UserTable WHERE ROLE = 'HOD'
)
BEGIN
SELECT * FROM UserTable WHERE ROLE = 'HOD'
END
ELSE BEGIN
SELECT * FROM UserTable WHERE ROLE = 'Supervisor'
END
This should do :
IF EXISTS(SELECT 1 FRom UserTable where role='HOD')
Begin
select * from UserTable where role='HOD'
END
ELSE BEGIN
select * from UserTable where role='Supervisor'
END
If you are using Transact SQL then a good page to read about this is https://learn.microsoft.com/en-us/sql/t-sql/language-elements/if-else-transact-sql
In the Transact SQL instance, the general version of what you are looking for is;
IF Boolean_expression
{ sql_statement | statement_block }
[ ELSE
{ sql_statement | statement_block } ]

Linked servers select taking way to long

Moving some complicated reporting sprocs to a centralized server and time went from 5 seconds to 30+ seconds.
validating what take so long via:
print '04 NWA Raw data Numeric'
print datediff(ss, #now, getdate())
set #now = GETDATE()
I am attempting to only pull local what this report needs with these queries:
1355 rows in 10 seconds----
select *
into #nwaDump
from [Phoenix].[NWA].dbo.QISDataNumeric
where rowguid in (
select rowguid from [Phoenix].[NWA].[dbo].[QISDataText] nd
where nd.DataValue in ( '41310291 ' )
)
249 rows in 28 seconds
select *
into #nwaText
from [Phoenix].[NWA].[dbo].[QISDataText] td
where td.DataValue in ( '41310291 ' )
Same two queries run on other server < 1 second return time.
Any ideas?
You can try to use OPENQUERY for this, since it should make the filters on the linked server and then pull them to your other server:
SELECT *
INTO #nwaText
FROM OPENQUERY(Phoenix,'SELECT * FROM [NWA].[dbo].[QISDataText]
WHERE DataValue in ( ''41310291 '' )')

SQL Server MERGE statement and ORDER BY clause

I would like to write a MERGE statement to pick TOP 10 rows from a large table by using ORDER BY clause and update it’s one of the column values. MERGE statement allows me to pick TOP 10 rows but I could not put ORDER BY clause anywhere.
MERGE TOP(10) StudentAllocation AS SA
USING (SELECT #sub_id AS subId) AS TSA ON SA.sub_id = TSA.subId
WHEN MATCHED THEN
UPDATE SET SA.exam_batch = 1);
You can use a table expression as both the source and target for the MERGE.
WITH SA AS
(
SELECT TOP(10) sub_id,
exam_batch
FROM StudentAllocation
ORDER BY sub_id
)
MERGE SA
USING (SELECT #sub_id AS subId) AS TSA ON SA.sub_id = TSA.subId
WHEN MATCHED THEN
UPDATE SET SA.exam_batch = 1;
although it might be simpler to use
WITH SA AS
(
SELECT TOP(10) sub_id,
exam_batch
FROM StudentAllocation
ORDER BY sub_id
)
UPDATE SA
SET exam_batch = 1
WHERE sub_id = #sub_id;

Add table data to itself, incrementing timestamp

I have a table with dummy data in it, with 40,000 rows, and a timestamp on each row that increments by a few milliseconds. I want to multiply these rows by, say, 10, each 40,000 rows incrementing by a day, and hour, whatever I set it to be.
Is there a way to select data from a table and then feed it back into itself with one column changed slightly?
FWIW, there are 33 columns on this table.
Any help is appreciated!
The mysql code from gustavotkg is along the right lines.
INSERT INTO mytable (event_ts, col1, col2)
SELECT event_ts + interval '1 day', col1, col2
FROM mytable
WHERE event_ts BETWEEN <something> AND <something else>
Repeat with different intervals for multiple copies.
It is unclear whether you want to just update the rows or also select them at the same time, or even insert new rows. Updating is very simple:
UPDATE tbl
SET col1 = col1*10
,ts = ts + interval '1 day'
To also return all rows like a SELECT statement would (the updated state!):
UPDATE tbl
SET col1 = col1*10
, ts = ts + interval '1 day'
RETURNING *
If you actually want to INSERT new rows with just one column changed and the timestamp changed, and the point is to avoid having to type out all 33 columns, you could:
CREATE TEMP TABLE tbl_tmp AS SELECT * FROM tbl;
UPDATE tbl_tmp SET col1 = col1*10, ts = ts + interval '1 day';
INSERT INTO tbl SELECT * FROM tbl_tmp;
DROP tbl_tmp;
OR somewhat faster with the new writable CTEs in version 9.1:
CREATE TEMP TABLE ON COMMIT DROP tbl_tmp AS SELECT * FROM tbl;
WITH x AS (
UPDATE tbl_tmp SET col1 = col1*10, ts = ts + interval '1 day'
RETURNING *
)
INSERT INTO tbl SELECT * FROM x;
DROP tbl_tmp;
Be sure to have autovacuum running or run VACUUM ANALYZE manually afterwards.

Resources