Обсуждение: pqReadData() error
Check this out. I have a table with the following structure. ip_ad char(20) type int2 bytes int8 dates datetime Newest data keeps getting filled every hour into the table and the oldest one hour data gets deleted. So you have the network traffic data for the last one day in this table which consists of 12 one hour summary blocks. Now to delete the oldest data I use the following SQL queries. create table tempdates as select distinct dates from daydata; delete from daydata where dates in (select b.dates from tempdates a, tempdates b where a.dates-b.dates > '22 hours'); So this deletes data from the table where the data is more than 1 day old. This works fine if the no. of rows are very small. But in my case approximately 500 new rows get inserted and 500 oldest rows get deleted every one hour. The query takes a long time and then gives me the following error "pqReadData() -- backend closed the channel unexpectedly. This probably means the backend terminated abnormally before or while processing the request. We have lost the connection to the backend, so further processing is impossible. Terminating." But it works efficiently if I give the following queries instead of the above one. All I do is replace the "in" with "=" create table tempdates as select distinct dates from daydata; delete from daydata where dates =(select b.dates from tempdates a, tempdates b where a.dates-b.dates > '22 hours'); But unfortunaltely for me I cannot use the above query because sometimes multiple rows might be retrurned from the subquery ie when some data is lost in between. Also if I substitute the subquery with actual values for dates , the query works really fast without giving any errors. I have tried all possible combinations of indexing also. Still I get the same error. Is ther any other way to work around it. I am using Postgres version 6.5.1 on Linux 2.0.36 Kernel ,Redhat 5.2 , Pentium PII 350 Mhz I have 32MB of Ram. Thanx in advance regards Imtiaz
"Imtiaz. S. M" <imtiaz_sm@yahoo.com> writes: > ... to delete the oldest data I use the following SQL queries. > create table tempdates as select distinct dates from daydata; > delete from daydata where dates in (select b.dates from tempdates a, > tempdates b where a.dates-b.dates > '22 hours'); This is certainly the hard, hard way to do it. Why not create table tempdates as select max(dates) - '22 hours'::interval as cutoff from daydata; delete from daydata where dates < (select cutoff from tempdates); As you have it, the subselect must generate O(N^2) rows for an N-row daydata table (assuming the distribution of dates is fairly even). If I read you correctly, there are about 12,000 rows in daydata at all times? If so the subselect will examine 144,000,000 pairs of a.dates and b.dates, and probably output about 25,000 rows (500 a rows matching each b row, and vice versa). That's a lot of data, and then it has to be scanned over for each row of the daydata table in order to implement the IN; the rows that you are keeping will require a comparison against *every single one* of the subselect output rows to verify that the IN fails. So about 11,500 * 25,000 row comparisons done by the IN just for the non-deleted rows, and probably a few million more for the deletable rows. Lots faster to calculate the cutoff time once and then do one compare for each row. You could probably simplify this even more, to delete from daydata where dates < (select max(dates) - '22 hours'::interval from daydata); unless you have some other use for the temp table's contents. > The query takes a long time and then gives me the > following error > "pqReadData() -- backend closed the channel unexpectedly. Probably all that date arithmetic is overflowing memory with temporary results ... which won't get reclaimed till end of query, at present. But even if it didn't run out of memory, doing it this way is very slow. regards, tom lane