Re: REINDEX CONCURRENTLY 2.0 - Mailing list pgsql-hackers
From | Andres Freund |
---|---|
Subject | Re: REINDEX CONCURRENTLY 2.0 |
Date | |
Msg-id | 20141113003106.GJ13473@awork2.anarazel.de Whole thread Raw |
In response to | Re: REINDEX CONCURRENTLY 2.0 (Robert Haas <robertmhaas@gmail.com>) |
Responses |
Re: REINDEX CONCURRENTLY 2.0
Re: REINDEX CONCURRENTLY 2.0 Re: REINDEX CONCURRENTLY 2.0 Re: REINDEX CONCURRENTLY 2.0 |
List | pgsql-hackers |
On 2014-11-12 18:23:38 -0500, Robert Haas wrote: > On Wed, Nov 12, 2014 at 4:39 PM, Andres Freund <andres@2ndquadrant.com> wrote: > > On 2014-11-12 16:11:58 -0500, Robert Haas wrote: > >> On Wed, Nov 12, 2014 at 4:10 PM, Robert Haas <robertmhaas@gmail.com> wrote: > >> > On Thu, Nov 6, 2014 at 9:50 AM, Peter Eisentraut <peter_e@gmx.net> wrote: > >> >> If REINDEX cannot work without an exclusive lock, we should invent some > >> >> other qualifier, like WITH FEWER LOCKS. > >> > > >> > What he said. > > > > I'm unconvinced. A *short* exclusive lock (just to update two pg_class > > row), still gives most of the benefits of CONCURRENTLY. > > I am pretty doubtful about that. It's still going to require you to > wait for all transactions to drain out of the table while new ones are > blocked from entering. Which sucks. Unless all of your transactions > are very short, but that's not necessarily typical. Yes, it sucks. But it beats not being able to reindex a relation with a primary key (referenced by a fkey) without waiting several hours by a couple magnitudes. And that's the current situation. > > The problem is that it's very hard to avoid the wrong index's > > relfilenode being used when swapping the relfilenodes between two > > indexes. > > How about storing both the old and new relfilenodes in the same pg_class entry? That's quite a cool idea [think a bit] But I think it won't work realistically. We have a *lot* of infrastructure that refers to indexes using it's primary key. I don't think we want to touch all those places to also disambiguate on some other factor. All the relevant APIs are either just passing around oids or relcache entries. There's also the problem that we'd really need two different pg_index rows to make things work. Alternatively we can duplicate the three relevant columns (indisready, indislive, indislive) in there for the different filenodes. But that's not entirely pretty. > 1. Take a snapshot. > 2. Index all the tuples in that snapshot. > 3. Publish the new relfilenode to an additional pg_class column, > relnewfilenode or similar. > 4. Wait until everyone can see step #3. Here all backends need to update both indexes, right? And all the indexing infrastructure can't deal with that without having separate oids & relcache entries. > 5. Rescan the table and add any missing tuples to the index. > 6. Set some flag in pg_class to mark the relnewfilenode as active and > relfilenode as not to be used for queries. > 7. Wait until everyone can see step #6. > 8. Set some flag in pg_class to mark relfilenode as not even to be opened. > 9. Wait until everyone can see step #8. > 10. Drop old relfilenode. > 11. Clean up by setting relfilenode = relnewfilenode, relfilenode = 0. Even that one isn't trivial - how do you deal with the fact that somebody looking at updating newrelfilenode might, in the midst of processing, see newrelfilenode = 0? I've earlier come up with a couple possible solutions, but I unfortunately found holes in all of them. And if I can find holes in them, there surely are more :(. I don't recall what the problem with just swapping the names was - but I'm pretty sure there was one... Hm. The index relation oids are referred to by constraints and dependencies. That's somewhat solvable. But I think there was something else as well... Greetings, Andres Freund -- Andres Freund http://www.2ndQuadrant.com/PostgreSQL Development, 24x7 Support, Training & Services
pgsql-hackers by date: