In the first post in this series I showed how the Power BI Service applies a limit on the total amount of time it takes to refresh a dataset in the Power BI Service, except when you initiate your refresh via an XMLA Endpoint. In this post I’ll look at the various timeouts that can be configured in Power Query functions that are used to access data.
Every time a Power BI Import mode dataset connects to a data source it goes through a Power Query query, and inside the code of that Power Query query will be an M function that connects to a specific type of data source. Most – but not all – of these M functions have the option to set timeouts. The M functions that connect to relational databases (for example Sql.Database which is used to connect to SQL Server-related sources, or Odbc.DataSource which is used to connect to ODBC sources) typically allow you to configure two types of timeout:
- A connection timeout, which specifies how long to wait when trying to open a connection to the data source
- A command timeout, which specifies how long the query to get data from the source is allowed to run
Some other functions have other timeouts more appropriate to the data source they access: for example Web.Contents and OData.Feed have a Timeout property for the HTTP requests they make behind the scenes. Other functions (for example Excel.Workbook) have no timeout-related properties that you can set at all. You should check the documentation , either online or using the #shared intrinsic variable in the Power Query Editor, to see what options are available and what the default timeouts are.
Here’s a simple example of how to set a timeout when connecting to SQL Server. First of all, I created a scalar function called ForceDelay in TSQL that returns a value of 1 after a specified number of seconds, so the query:
select [dbo].[ForceDelay](10) as MyColumn
…takes 10 seconds to run.
When you connect to SQL Server in Power BI/Power Query you can paste a SQL query in the connection dialog under Advanced Options; when you do so you’ll also see the option to set the command timeout in minutes:
Here’s the M code generated when you use the SQL query above, set the Command timeout to 1 minute and click OK:
let Source = Sql.Database( "localhost", "AdventureWorksDW2017", [ Query = "select [dbo].[ForceDelay](10) as MyColumn", CommandTimeout = #duration( 0, 0, 1, 0 ) ] ) in Source
Notice that the CommandTimeout option has been set on the Sql.Database function, and that the value passed to it is a duration of one minute defined using #duration. Since the SQL query takes 10 seconds to run and the timeout is 1 minute, it runs successfully.
However, if you set the CommandTimeout option to 5 seconds like so:
let Source = Sql.Database( "localhost", "AdventureWorksDW2017", [ Query = "select [dbo].[ForceDelay](10) as MyColumn", CommandTimeout = #duration( 0, 0, 0, 5 ) ] ) in Source
…then the query will take longer that the timeout and you’ll see the following error in the Power Query Editor:
The error message is:
DataSource.Error: Microsoft SQL: Execution Timeout Expired. The timeout period elapsed prior to completion of the operation or the server is not responding.
If you hit the timeout when refreshing in the main Power BI window you’ll see the same message in the refresh dialog box:
So, as you can see, if you are working with large data volumes or slow queries you will need to be aware of the default timeouts set in the M functions you’re using and alter them if need be.