We have a client side application that allows very complex reporting on large data sets. On the left hand side is a tree of possible columns to include in the report, and on the right hand side is a table where we dynamically populate the results.
When a user clicks on the columns they want to include in their report, we're building the necessary SQL (often including a lot of joins and complex sub-queries), and firing those queries off asynchronously.
Problem: Users are creating complex reports resulting in very complex and costly queries. These queries end up backing up and causing us to run out of connections.
I ended up finding sections of our logs that look like this:
169077:2019-09-11 22:14:29 UTC LOG: duration: 65018.497 ms execute <unnamed>:
169105:2019-09-11 22:14:31 UTC LOG: duration: 22494.712 ms execute <unnamed>: SELEC
169129:2019-09-11 22:14:34 UTC LOG: duration: 67866.947 ms execute <unnamed>:
169157:2019-09-11 22:14:40 UTC LOG: duration: 51176.815 ms execute <unnamed>:
169185:2019-09-11 22:14:41 UTC LOG: duration: 51836.988 ms execute <unnamed>:
169213:2019-09-11 22:14:42 UTC LOG: duration: 52655.482 ms execute <unnamed>:
169244:2019-09-11 22:14:46 UTC LOG: duration: 55871.561 ms execute <unnamed>:
Ouch! You can see by the timestamps this is a user adding more columns they want to report on (I confirmed by looking at the queries), blissfully unaware of the pain our database is going through.
Here are some solutions I thought of:
1) Remove the asynchronous querying, making the end user build the report first, then clicking a button to actually run it. This is not ideal as our current user base (which is quite large) would definitely be confused if we made this change (it's unfortunately a UX digression).
2) When the end user clicks a column and the query is fired off asynchronously, somehow trace the PID of the query that is actually running within Postgres. When the same user clicks another column, kill the previous PID, and start tracking the new PID. This would ensure only one query is running for this end user during the report building process at any given time, and would prevent the long running query buildup as seen in the example above.
Is #2 even possible? I looked at possible tracing with probes, and looked at PGBouncer briefly, but I'm not too familiar with either and wasn't able to find a definitive answer.
Any thoughts or suggestions are welcome!
Here is a generic approach to implementing #2 on the client side.
It looks like you are after the pg_backend_pid function.
Call it after establishing the connection, remember your PID, then start your async query using that connection and PID.
If it turns out that you need to stop the query later, use pg_cancel_backend with the PID remembered previously to cancel it.
Or, you can use functions specific to the library that you use to connect to Postgres.
For example, if you use libpq, you can use PQcancel function to stop the query.
Related
I have a sql file running many queries. I want to see the accumualted sum of all queries. I know that if I turn on timing, or call
\timing
query 1;
query 2;
query 3;
...
query n;
at the beginning of the script, it will start to show time it takes for each query to run. However, I need to have the accumulate results of all queries, without having to manually add them.
Is there a systematic way? If not, how can I fetch the interim times to throw them in a variable.
The pg_stat_statements is a good module that provides a means for tracking execution statistics.
First, add pg_stat_statements to shared_preload_libraries in the
postgresql.conf file. To know where this .conf file exists in your
filesystem, run show config_file;
shared_preload_libraries = 'pg_stat_statements'
Restart Postgres database
Create the extension
CREATE EXTENSION pg_stat_statements;
Now, the module provides a View, pg_stat_statements, which helps you to analyze various query execution metrics.
Reset the contents of stat collected before running queries.
SELECT pg_stat_statements_reset();
Now, execute your script file containing queries.
\i script_file.sql
You may get all the timing statistics of all the queries executed. To get the total time taken, simply run
select sum(total_time) from pg_stat_statements
where query !~* 'pg_stat_statements';
The time you get is in milliseconds, which may be converted to desired format using various timestamp related Postgres functions
If you want to time the whole script, on linux or mac you can use the time utility to launch the script.
The measurement in this case is a bit more than the sum of the raw query times, because it includes some overhead of starting and running the psql command. On my system this overhead is around 20ms.
$ time psql < script.sql
…
real 0m0.117s
user 0m0.008s
sys 0m0.007s
The real value is the time it took to execute the whole script, including the aforementioned overhead.
The approach in this answer is a crude, simple client side way to measure the runtime of the overall script. It is not useful to measure milli-second precision server side execution times. It still might be sufficient for many use-cases.
The solution of Kaushik Nayak is a way more precise method to time executions directly on the server. It also provides much more insight into the execution (eg. query level times).
Hi i connected Hive using DB visualizer and fired a simple join query to fetch two columns according to the filter applied. But the query was running for more than an hour with the status "Executing". I fired the same query in Hive logging through Putty and got the result in less than 20 seconds.
Can anyone help me to understand why the query in DB visualizer was running for a long time without producing any output.
Query used:
SELECT
A.ORDER,
B.ORDER1
FROM
ORDER A
INNER JOIN DUORDER B ON A.ORDER=B.ORDER1 AND A.TYPE ='50'
(The result set contain only 400 records)
To analyze why, we need more info. Please please open Tools->Debug Window in DbVisualizer and enable debugging (just for DbVisualizer, not JDBC). Execute the query again, stopping it after some time (say a few minutes). Then submit a support request using Help->Contact Support, and make sure that Attach Logs is enabled. This will give us the info we need to see what may be wrong.
Best Regards,
Hans (DbVisualizer team)
When I execute a query for the first time in DBeaver it can take up to 10-15 seconds to display the result. In SQLDeveloper those queries only take a fraction of that time.
For example:
Simple "select column1 from table1" statement
DBeaver: 2006ms,
SQLDeveloper: 306ms
Example 2 (other way around; so theres no server-side caching):
Simple "select column1 from table2" statement
SQLDeveloper: 252ms,
DBeaver: 1933ms
DBeavers status box says:
Fetch resultset
Discover attribute column1
Find attribute column1
Late bind attribute colummn1
2, 3 and 4 use most of the query execution time.
I'm using oracle 11g, SQLDeveloper 4.1.1.19 and DBeaver 3.5.8.
See http://dbeaver.jkiss.org/forum/viewtopic.php?f=2&t=1870
What could be the cause?
DBeaver looks up some metadata related to objects in your query.
On an Oracle DB, it queries catalog tables such as
SYS.ALL_ALL_TABLES / SYS.ALL_OBJECTS - only once after connection, for the first query you execute
SYS.ALL_TAB_COLS / SYS.ALL_INDEXES / SYS.ALL_CONSTRAINTS / ... - I believe each time you query a table not used before.
Version 3.6.10 introduced an option to enable/disable a hint used in those queries. Disabling the hint made a huge difference for me. The option is in the Oracle Properties tab of the connection edit dialog. Have a look at issue 360 on dbeaver's github for more info.
The best way to get insight is to perfom the database trace
Perform few time the query to eliminate the caching effect.
Than repeat in both IDEs following steps
activate the trace
ALTER SESSION SET tracefile_identifier = test_IDE_xxxx;
alter session set events '10046 trace name context forever, level 12'; /* binds + waits */
Provide the xxxx to identify the test. You will see this string as a part of the trace file name.
Use level 12 to see the wait events and bind variables.
run the query
close the conenction
This is important to not trace other things.
Examine the two trace files to see:
what statements were performed
what number of rows was fetched
what time was elapsed in DB
for the rest of the time the client (IDE) is responsible
This should provide you enough evidence to claim if one IDE behaves different than other or if simple the DB statements issued are different.
I would like to be able to tag an SQL query somehow, so I can relate the query execution to the web request that triggered the query. I already have a unique request id, that I tag my logs and other monitoring with, so I can easily do a complete trace across the weblogs and new relic for example.
But when I look at a report of long running SQL queries for example, I cannot trace that back to the request that triggered the SQL Query. I would really like to be able to tag the query with my request id somehow.
I can't find anything online. When I search I just find blogs about storing tags and tag clouds in SQL. Not really what I need.
Hope the question makes sense.
This is a very interesting post...
I hope, adding an extra nullable parameter to your stored procedure(s) will ensure that the profiler will catch the unique id passed during a call (in the trace) whether you use that parameter inside the procedure or not (i.e. to do something meaningful...like inserting into an audit table with unique id, procedure name, timestamp etc).
But I think that will make life difficult as you now have to update all your procedures.
If you already have logging turned on (web server) and it captures the same unique id in its request (log file) along with a timestamp then you probably can code a small utility app that reads the log file and find matching entries in the traced table by the timestamp alone.
The only thing that might go wrong is if your web server and database server have differeing times (you need to offset your calculation accordingly).
I don't know if this will help but it is certainly a very interesting project and I am hoping somebody have experienced this thing and came up with a nice solution.
Will be closely watching this post if such a solution exists....
All the best...
If I understand correctly, you want to follow up the query execution in Activity Monitor. But have you considered using a DMV or SQL PROFILER ?
In my opinion, your best bet would be to wrap it in a stored proc. This way you will be able to FILTER your trace only for this object. Here's an example of a simple select and the same select wrapped in stored proc named sproc1 :
As you can see in this image, you can start a SQL PROFILER trace and filter it on the ObjectName. You can then add other column like CPU, StartTime, ...
If you can't use a stored proc, then I would suggest to insert a comment before the exec like this:
/* ID1234 */
select * from table1
Then use SQL PROFILER the same way but you now filter on the TextData using your ID
Here the result :
I am having this big database on one MSSQL server that contains data indexed by a web crawler.
Every day I want to update SOLR SearchEngine Index using DataImportHandler which is situated in another server and another network.
Solr DataImportHandler uses query to get data from SQL. For example this query
SELECT * FROM DB.Table WHERE DateModified > Config.LastUpdateDate
The ImportHandler does 8 selects of this types. Each select will get arround 1000 rows from database.
To connect to SQL SERVER i am using com.microsoft.sqlserver.jdbc.SQLServerDriver
The parameters I can add for connection are:
responseBuffering="adaptive/all"
batchSize="integer"
So my question is:
What can go wrong while doing this queries every day ? ( except network errors )
I want to know how is SQL Server working in this context ?
Further more I have to take a decicion regarding the way I will implement this importing and how to handle errors, but first I need to know what errors can arise.
Thanks!
Later edit
My problem is that I don't know how can this SQL Queries fail. When i am calling this importer every day it does 10 queries to the database. If 5th query fails I have to options:
rollback the entire transaction and do it again, or commit the data I got from the first 4 queries and redo somehow the queries 5 to 10. But if this queries always fails, because of some other problems, I need to think another way to import this data.
Can this sql queries over internet fail because of timeout operations or something like this?
The only problem i identified after working with this type of import is:
Network problem - If the network connection fails: in this case SOLR is rolling back any changes and the commit doesn't take place. In my program I identify this as an error and don't log the changes in the database.
Thanks #GuidEmpty for providing his comment and clarifying out this for me.
There could be issues with permissions (not sure if you control these).
Might be a good idea to catch exceptions you can think of and include a catch all (Exception exp).
Then take the overall one as a worst case and roll-back (where you can) and log the exception to include later on.
You don't say what types you are selecting either, keep in mind text/blob can take a lot more space and could cause issues internally if you buffer any data etc.
Though just a quick re-read and you don't need to roll-back if you are only selecting.
I think you would be better having a think about what you are hoping to achieve and whether knowing all possible problems will help?
HTH