From robert.head at gmail.com Fri Feb 2 17:33:06 2007 From: robert.head at gmail.com (Robert Head) Date: Fri, 2 Feb 2007 14:33:06 -0800 Subject: [Betternestedset-talk] Performance of parent, full_set, all_children, and children Message-ID: <43e309bd0702021433w28302636scefd0c4ff3100d4b@mail.gmail.com> I recently implemented better_nested_set in a forum project and found that every time I called parent, full_set, all_children, or children, the DB got hit again. To fix this I overrode those methods as has_many and belongs_to relationships, which are, apparently, cached by ActiveRecord. Why no caching? Is this a known limitation or am I missing something? Many thanks, Robert Head ----- Here's my code: class Post < ActiveRecord::Base # blah, blah, blah... acts_as_nested_set :left_column => "lft", :right_column => "rgt", :scope => :topic, :text_column => 'subject' # use faster relationships for familial relationships alias nested_set_children children has_many :children, :class_name => "Post", :order => "lft", :foreign_key => :parent_id has_many :self_and_descendants, :class_name => "Post", :order => "lft", :finder_sql => 'SELECT * FROM posts WHERE topic_id = #{topic_id} AND (lft BETWEEN #{lft} AND #{rgt})' alias nested_set_parent parent belongs_to :parent, :class_name => "Post", :foreign_key => :parent_id # yadda, yadda, yadda... end -------------- next part -------------- An HTML attachment was scrubbed... URL: http://rubyforge.org/pipermail/betternestedset-talk/attachments/20070202/952c35b4/attachment.html From dontfall at gmail.com Fri Feb 2 17:46:28 2007 From: dontfall at gmail.com (Krishna Dole) Date: Fri, 2 Feb 2007 17:46:28 -0500 Subject: [Betternestedset-talk] Performance of parent, full_set, all_children, and children In-Reply-To: <43e309bd0702021433w28302636scefd0c4ff3100d4b@mail.gmail.com> References: <43e309bd0702021433w28302636scefd0c4ff3100d4b@mail.gmail.com> Message-ID: <8d64b97d0702021446j11739200ua772076b6ec277c9@mail.gmail.com> Hey Robert, In a word, you're right. The trunk version of better nested set doesn't take this approach because the attribute setting methods of the associations would cause problems (Item.children.create(), Item.parent=). However, in the branch I'm working on (branches/ez-set) I do use the approach you are describing. If I can get a few performance concerns addressed in this branch it may become the trunk version. cheers, Krishna On 2/2/07, Robert Head wrote: > I recently implemented better_nested_set in a forum project and found that > every time I called parent, full_set, all_children, or children, the DB got > hit again. > > To fix this I overrode those methods as has_many and belongs_to > relationships, which are, apparently, cached by ActiveRecord. > > Why no caching? Is this a known limitation or am I missing something? > > Many thanks, > Robert Head > > ----- > > Here's my code: > > class Post < ActiveRecord::Base > > # blah, blah, blah... > > acts_as_nested_set :left_column => "lft", :right_column => "rgt", :scope > => :topic, :text_column => 'subject' > > # use faster relationships for familial relationships > > alias nested_set_children children > has_many :children, :class_name => "Post", :order => "lft", :foreign_key > => :parent_id > > has_many :self_and_descendants, :class_name => "Post", :order => "lft", > :finder_sql => 'SELECT * FROM posts WHERE topic_id = #{topic_id} AND > (lft BETWEEN #{lft} AND #{rgt})' > > alias nested_set_parent parent > belongs_to :parent, :class_name => "Post", :foreign_key => :parent_id > > # yadda, yadda, yadda... > > end > > > _______________________________________________ > Betternestedset-talk mailing list > Betternestedset-talk at rubyforge.org > http://rubyforge.org/mailman/listinfo/betternestedset-talk > > > From robert.head at gmail.com Fri Feb 2 18:38:27 2007 From: robert.head at gmail.com (Robert Head) Date: Fri, 2 Feb 2007 15:38:27 -0800 Subject: [Betternestedset-talk] Performance of parent, full_set, all_children, and children In-Reply-To: <8d64b97d0702021446j11739200ua772076b6ec277c9@mail.gmail.com> References: <43e309bd0702021433w28302636scefd0c4ff3100d4b@mail.gmail.com> <8d64b97d0702021446j11739200ua772076b6ec277c9@mail.gmail.com> Message-ID: <43e309bd0702021538m2e1a83b1ud36bb23ad20a5f8e@mail.gmail.com> Thanks very much for the info. It confirms my approach. And good luck with integrating the performance improvements. They sound like a good thing. Cheers, Rob On 2/2/07, Krishna Dole wrote: > > Hey Robert, > > In a word, you're right. The trunk version of better nested set > doesn't take this approach because the attribute setting methods of > the associations would cause problems (Item.children.create(), > Item.parent=). However, in the branch I'm working on (branches/ez-set) > I do use the approach you are describing. If I can get a few > performance concerns addressed in this branch it may become the trunk > version. > > cheers, > Krishna > > On 2/2/07, Robert Head wrote: > > I recently implemented better_nested_set in a forum project and found > that > > every time I called parent, full_set, all_children, or children, the DB > got > > hit again. > > > > To fix this I overrode those methods as has_many and belongs_to > > relationships, which are, apparently, cached by ActiveRecord. > > > > Why no caching? Is this a known limitation or am I missing something? > > > > Many thanks, > > Robert Head > > > > ----- > > > > Here's my code: > > > > class Post < ActiveRecord::Base > > > > # blah, blah, blah... > > > > acts_as_nested_set :left_column => "lft", :right_column => "rgt", > :scope > > => :topic, :text_column => 'subject' > > > > # use faster relationships for familial relationships > > > > alias nested_set_children children > > has_many :children, :class_name => "Post", :order => "lft", > :foreign_key > > => :parent_id > > > > has_many :self_and_descendants, :class_name => "Post", :order => > "lft", > > :finder_sql => 'SELECT * FROM posts WHERE topic_id = #{topic_id} > AND > > (lft BETWEEN #{lft} AND #{rgt})' > > > > alias nested_set_parent parent > > belongs_to :parent, :class_name => "Post", :foreign_key => :parent_id > > > > # yadda, yadda, yadda... > > > > end > > > > > > _______________________________________________ > > Betternestedset-talk mailing list > > Betternestedset-talk at rubyforge.org > > http://rubyforge.org/mailman/listinfo/betternestedset-talk > > > > > > > _______________________________________________ > Betternestedset-talk mailing list > Betternestedset-talk at rubyforge.org > http://rubyforge.org/mailman/listinfo/betternestedset-talk > -------------- next part -------------- An HTML attachment was scrubbed... URL: http://rubyforge.org/pipermail/betternestedset-talk/attachments/20070202/18402283/attachment.html From jeff at jefdean.com Fri Feb 9 16:22:08 2007 From: jeff at jefdean.com (Jeff Dean) Date: Fri, 9 Feb 2007 16:22:08 -0500 Subject: [Betternestedset-talk] Improving the nested_set model to remove redundancy Message-ID: <246e442a0702091322ve020d80k82b7c0375f174b9b@mail.gmail.com> I've been working with the Celko sets a bit lately and looking at the rails nested_set and better_nested_set and I think there are a few redundancies/areas of improvement for performance in both models. I may not understand the issues well, so please excuse me if these points are naive: First, I think the parent_id field is completely unnecessary. The point of the nested set model seems to be that you eliminate the need for the join, thereby creating a table with a single fact, in a single place. If you don't have a parent_id, you identify a root as anything with lft=1. You can achieve multiple roots by using composite keys (by adding a set_id column, for example). Second, the numbering scheme need not be contiguous. If you use the full range of floats given in a database you can insert thousands of children without ever having to recalculate other rows in the database. This will drastically increase performance on inserts/updates, and unless you are working with huge sets, you may never need to recalculate parent boundaries. For more information (if you haven't already seen it), check out: http://searchoracle.techtarget.com/tip/1,289483,sid13_gci537290,00.html Way down the page, Celko talks about "1) The Algebra Property: For each node (n), (rgt-lft+1)/2 = size of subtree rooted at (n). This requires that the union of the rgt and lft numbers be an unbroken sequence, no gaps. 2) The Between-ness Property that you can find superiors and subordinates with a BETWEEN predicate" Further reading on how to perform much more complex calculations, check out: http://www.dbazine.com/oracle/or-articles/tropashko4 Is there any reason why we would need to keep parent_id or unbroken sequences? -------------- next part -------------- An HTML attachment was scrubbed... URL: http://rubyforge.org/pipermail/betternestedset-talk/attachments/20070209/fd9a012e/attachment.html From dontfall at gmail.com Fri Feb 9 19:15:16 2007 From: dontfall at gmail.com (Krishna Dole) Date: Fri, 9 Feb 2007 19:15:16 -0500 Subject: [Betternestedset-talk] Improving the nested_set model to remove redundancy In-Reply-To: <246e442a0702091322ve020d80k82b7c0375f174b9b@mail.gmail.com> References: <246e442a0702091322ve020d80k82b7c0375f174b9b@mail.gmail.com> Message-ID: <8d64b97d0702091615n53c1227eifbc9fe4bf31af230@mail.gmail.com> Hi Jeff, Thanks for writing us about this, and welcome to the list. > First, I think the parent_id field is completely unnecessary. The point of > the nested set model seems to be that you eliminate the need for the join, > thereby creating a table with a single fact, in a single place. If you > don't have a parent_id, you identify a root as anything with lft=1. You can > achieve multiple roots by using composite keys (by adding a set_id column, > for example). You're right-- strictly speaking the parent_id field is unnecessary, and thus non-normalized. However, we have chosen to keep it thus far for several reasons: 1) It provides a good backup to the lft/rgt indexes. Nested sets are inherently both volatile and brittle. I feel good about our code's ability to maintain the left/right values, but if they somehow became corrupted, repairing them without having parent_id would be a devilish manual process at best and impossible at worst. We provide handy methods for both checking and re-indexing using the parent_id. 2) It provides significant performance advantages in a number of situations: the common task of fetching a node's parent is _much_ faster using parent_id. Fetching immediate children would require a 'level' column if the parent_id was not present, and maintaining a level column would be a bit of work. (But nice to have-- it's on the to-do list) 3) It makes reversion to an adjacency-list model trivial (just nuke the lft and rgt cols) if you decide nested sets aren't for you. One of my goals with the code is to make it easy for people using acts_as_tree to try a nested set model. 4) The parent_id is required (and used to good effect) in the ez-set branch. 5) It doesn't really cause any problems, performance or otherwise. > > Second, the numbering scheme need not be contiguous. If you use the full > range of floats given in a database you can insert thousands of children > without ever having to recalculate other rows in the database. This will > drastically increase performance on inserts/updates, and unless you are > working with huge sets, you may never need to recalculate parent boundaries. I looked into using floats, but I was turned off by the fact that trees less than 60 levels deep (if I recall correctly) could overrun the index. That said, if you would like to try implementing something like this, please do-- I'm happy to provide what advice I can. Keeping the index sequential has a few benefits: you can find out how many descendants a node has without hitting the database, and it makes finding 'leaf' nodes easy. > > For more information (if you haven't already seen it), check out: > > http://searchoracle.techtarget.com/tip/1,289483,sid13_gci537290,00.html Thanks for linking to that. I'd seen most of it before (Joe has recycled that material a lot of times), but some of the information at the bottom was interesting. Cheers, Krishna From jeff at jefdean.com Fri Feb 9 19:49:23 2007 From: jeff at jefdean.com (Jeff Dean) Date: Fri, 9 Feb 2007 19:49:23 -0500 Subject: [Betternestedset-talk] Improving the nested_set model to remove redundancy In-Reply-To: <8d64b97d0702091615n53c1227eifbc9fe4bf31af230@mail.gmail.com> References: <246e442a0702091322ve020d80k82b7c0375f174b9b@mail.gmail.com> <8d64b97d0702091615n53c1227eifbc9fe4bf31af230@mail.gmail.com> Message-ID: <246e442a0702091649g309b4fefyb0ca66a27556aa68@mail.gmail.com> All good points - thanks for the clarification! On 2/9/07, Krishna Dole wrote: > > Hi Jeff, > > Thanks for writing us about this, and welcome to the list. > > > First, I think the parent_id field is completely unnecessary. The point > of > > the nested set model seems to be that you eliminate the need for the > join, > > thereby creating a table with a single fact, in a single place. If you > > don't have a parent_id, you identify a root as anything with lft=1. You > can > > achieve multiple roots by using composite keys (by adding a set_id > column, > > for example). > > You're right-- strictly speaking the parent_id field is unnecessary, > and thus non-normalized. However, we have chosen to keep it thus far > for several reasons: > > 1) It provides a good backup to the lft/rgt indexes. Nested sets are > inherently both volatile and brittle. I feel good about our code's > ability to maintain the left/right values, but if they somehow became > corrupted, repairing them without having parent_id would be a devilish > manual process at best and impossible at worst. We provide handy > methods for both checking and re-indexing using the parent_id. > > 2) It provides significant performance advantages in a number of > situations: the common task of fetching a node's parent is _much_ > faster using parent_id. Fetching immediate children would require a > 'level' column if the parent_id was not present, and maintaining a > level column would be a bit of work. (But nice to have-- it's on the > to-do list) > > 3) It makes reversion to an adjacency-list model trivial (just nuke > the lft and rgt cols) if you decide nested sets aren't for you. One of > my goals with the code is to make it easy for people using > acts_as_tree to try a nested set model. > > 4) The parent_id is required (and used to good effect) in the ez-set > branch. > > 5) It doesn't really cause any problems, performance or otherwise. > > > > > Second, the numbering scheme need not be contiguous. If you use the > full > > range of floats given in a database you can insert thousands of children > > without ever having to recalculate other rows in the database. This > will > > drastically increase performance on inserts/updates, and unless you are > > working with huge sets, you may never need to recalculate parent > boundaries. > > I looked into using floats, but I was turned off by the fact that > trees less than 60 levels deep (if I recall correctly) could overrun > the index. That said, if you would like to try implementing something > like this, please do-- I'm happy to provide what advice I can. > > Keeping the index sequential has a few benefits: you can find out how > many descendants a node has without hitting the database, and it makes > finding 'leaf' nodes easy. > > > > > For more information (if you haven't already seen it), check out: > > > > http://searchoracle.techtarget.com/tip/1,289483,sid13_gci537290,00.html > > Thanks for linking to that. I'd seen most of it before (Joe has > recycled that material a lot of times), but some of the information at > the bottom was interesting. > > Cheers, > Krishna > _______________________________________________ > Betternestedset-talk mailing list > Betternestedset-talk at rubyforge.org > http://rubyforge.org/mailman/listinfo/betternestedset-talk > -------------- next part -------------- An HTML attachment was scrubbed... URL: http://rubyforge.org/pipermail/betternestedset-talk/attachments/20070209/feac712d/attachment-0001.html From joao.gomes at gmail.com Wed Feb 14 17:26:26 2007 From: joao.gomes at gmail.com (=?ISO-8859-1?Q?Jo=E3o_Gomes?=) Date: Wed, 14 Feb 2007 22:26:26 +0000 Subject: [Betternestedset-talk] Error after upgrade from acts_as_nested_set Message-ID: <166135A0-49E8-45F6-82F5-EE2D3557CF00@gmail.com> Hi, I'm getting this error just after installing the BetterNestedSet plugin: Unknown key(s): order /Applications/WebTools/Locomotive2/Bundles/ standardRailsSept2006.locobundle/i386/lib/ruby/gems/1.8/gems/ activesupport-1.3.1/lib/active_support/core_ext/hash/keys.rb:48:in `assert_valid_keys' /Applications/WebTools/Locomotive2/Bundles/ standardRailsSept2006.locobundle/i386/lib/ruby/gems/1.8/gems/ activerecord-1.14.4/lib/active_record/base.rb:840:in `with_scope' #{RAILS_ROOT}/vendor/plugins/betternestedset/lib/better_nested_set.rb: 94:in `find_in_nested_set' #{RAILS_ROOT}/vendor/plugins/betternestedset/lib/better_nested_set.rb: 478:in `direct_children' Anyone knows why? Thanks in advance, Joao Gomes -------------- next part -------------- An HTML attachment was scrubbed... URL: http://rubyforge.org/pipermail/betternestedset-talk/attachments/20070214/4f5746e2/attachment.html From dontfall at gmail.com Wed Feb 14 18:17:18 2007 From: dontfall at gmail.com (Krishna Dole) Date: Wed, 14 Feb 2007 18:17:18 -0500 Subject: [Betternestedset-talk] Error after upgrade from acts_as_nested_set In-Reply-To: <166135A0-49E8-45F6-82F5-EE2D3557CF00@gmail.com> References: <166135A0-49E8-45F6-82F5-EE2D3557CF00@gmail.com> Message-ID: <8d64b97d0702141517k6a5ca01cy6ef01acf6f284617@mail.gmail.com> Hi Jo?o, Thanks for the bug report. I suspect this may be an incompatibility with older versions of Rails. If you don't want to upgrade Rails you can install a less bleeding-edge version of better nested set: script/plugin install svn://rubyforge.org/var/svn/betternestedset/tags/stable/betternestedset Let us know if you go that route and it fixes the problem. Fabien-- you wrote the find_in_nested_set method, do you have any input? cheers, Krishna On 2/14/07, Jo?o Gomes wrote: > Hi, > > I'm getting this error just after installing the BetterNestedSet plugin: > > Unknown key(s): order > > /Applications/WebTools/Locomotive2/Bundles/standardRailsSept2006.locobundle/i386/lib/ruby/gems/1.8/gems/activesupport-1.3.1/lib/active_support/core_ext/hash/keys.rb:48:in > `assert_valid_keys' > /Applications/WebTools/Locomotive2/Bundles/standardRailsSept2006.locobundle/i386/lib/ruby/gems/1.8/gems/activerecord-1.14.4/lib/active_record/base.rb:840:in > `with_scope' > #{RAILS_ROOT}/vendor/plugins/betternestedset/lib/better_nested_set.rb:94:in > `find_in_nested_set' > #{RAILS_ROOT}/vendor/plugins/betternestedset/lib/better_nested_set.rb:478:in > `direct_children' > > Anyone knows why? > > Thanks in advance, > Joao Gomes > _______________________________________________ > Betternestedset-talk mailing list > Betternestedset-talk at rubyforge.org > http://rubyforge.org/mailman/listinfo/betternestedset-talk > > From joao.gomes at gmail.com Wed Feb 14 18:41:05 2007 From: joao.gomes at gmail.com (=?ISO-8859-1?Q?Jo=E3o_Gomes?=) Date: Wed, 14 Feb 2007 23:41:05 +0000 Subject: [Betternestedset-talk] Error after upgrade from acts_as_nested_set In-Reply-To: <8d64b97d0702141517k6a5ca01cy6ef01acf6f284617@mail.gmail.com> References: <166135A0-49E8-45F6-82F5-EE2D3557CF00@gmail.com> <8d64b97d0702141517k6a5ca01cy6ef01acf6f284617@mail.gmail.com> Message-ID: I upgraded Rails to version 1.2.2 but the error is the same. No error using the stable version. Thanks, Jo?o Gomes On 2007/02/14, at 23:17, Krishna Dole wrote: > Hi Jo?o, > > Thanks for the bug report. I suspect this may be an incompatibility > with older versions of Rails. If you don't want to upgrade Rails you > can install a less bleeding-edge version of better nested set: > > script/plugin install > svn://rubyforge.org/var/svn/betternestedset/tags/stable/ > betternestedset > > Let us know if you go that route and it fixes the problem. > > Fabien-- you wrote the find_in_nested_set method, do you have any > input? > > cheers, > Krishna > > > > On 2/14/07, Jo?o Gomes wrote: >> Hi, >> >> I'm getting this error just after installing the BetterNestedSet >> plugin: >> >> Unknown key(s): order >> >> /Applications/WebTools/Locomotive2/Bundles/ >> standardRailsSept2006.locobundle/i386/lib/ruby/gems/1.8/gems/ >> activesupport-1.3.1/lib/active_support/core_ext/hash/keys.rb:48:in >> `assert_valid_keys' >> /Applications/WebTools/Locomotive2/Bundles/ >> standardRailsSept2006.locobundle/i386/lib/ruby/gems/1.8/gems/ >> activerecord-1.14.4/lib/active_record/base.rb:840:in >> `with_scope' >> #{RAILS_ROOT}/vendor/plugins/betternestedset/lib/ >> better_nested_set.rb:94:in >> `find_in_nested_set' >> #{RAILS_ROOT}/vendor/plugins/betternestedset/lib/ >> better_nested_set.rb:478:in >> `direct_children' >> >> Anyone knows why? >> >> Thanks in advance, >> Joao Gomes >> _______________________________________________ >> Betternestedset-talk mailing list >> Betternestedset-talk at rubyforge.org >> http://rubyforge.org/mailman/listinfo/betternestedset-talk >> >> > _______________________________________________ > Betternestedset-talk mailing list > Betternestedset-talk at rubyforge.org > http://rubyforge.org/mailman/listinfo/betternestedset-talk From lindsaye at gmail.com Thu Feb 15 22:32:46 2007 From: lindsaye at gmail.com (Lindsay Evans) Date: Fri, 16 Feb 2007 14:32:46 +1100 Subject: [Betternestedset-talk] MySQL performance with large tables Message-ID: Hi all, Just joined the list, I checked through the archives & tickets, but couldn't find anything similar. I've recently started using better nested set on a project, and found that the performance was rather horrible on an InnoDB table with ~2.2 million rows (~27 seconds on a self_and_ancestors call, set is about 5 levels deep) After a bit of digging I discovered that MySQL was ignoring the indexes I'd set on the lft & rgt columns when using the BETWEEN operator. According to the MySQL docs, between is equivalent to (min <= expr AND expr <= max) , after replacing all the instances with this syntax, the query time went down to ~0.5sec, quite an improvement :) This has been working fine for me so far, but it would be great to hear others opinions on whether this will cause any other problems. I've attached a patch if anyone wants to check it out for themselves. I haven't tested this very extensively apart from in my app, just ran the unit tests & they all passed (after updating the test_sql_for to use the same syntax). I've also only tested this with MySQL 5, so I have no idea how these changes would effect other databases. -- Lindsay Evans http://lindsayevans.com/ -------------- next part -------------- A non-text attachment was scrubbed... Name: better_nested_set.rb.diff Type: application/octet-stream Size: 6686 bytes Desc: not available Url : http://rubyforge.org/pipermail/betternestedset-talk/attachments/20070216/abf328cb/attachment.obj From dontfall at gmail.com Fri Feb 16 13:01:16 2007 From: dontfall at gmail.com (Krishna Dole) Date: Fri, 16 Feb 2007 13:01:16 -0500 Subject: [Betternestedset-talk] MySQL performance with large tables In-Reply-To: References: Message-ID: <8d64b97d0702161001o69dba910u81348a1788d17aed@mail.gmail.com> Hi Lindsay, Welcome to the list. Thanks a lot for letting us know about this. I've looked into it some, and what I have seen is puzzling. For the relatively small (16,000 row) table I'm working on, I saw no difference between the two types of syntax for an ancestors query: http://pastie.caboo.se/40831 The odd part was that when I dropped the indexes, the descendants query got slower (as expected) but the ancestors query got faster using both 'between' and '<=' syntax: http://pastie.caboo.se/40850 I'm not enough of a database person to know if this behavior is expected on small tables, but I thought it was odd. (I tried all of these queries several times, and the times were consistent). I have heard that while the descendants query in a nested set is straightforward, the ancestors query is inherently difficult for databases to deal with. Thanks for the patch-- I'll do some more testing with larger tables and see what I can figure out. Cheers, Krishna On 2/15/07, Lindsay Evans wrote: > Hi all, > > Just joined the list, I checked through the archives & tickets, but > couldn't find anything similar. > > I've recently started using better nested set on a project, and found > that the performance was rather horrible on an InnoDB table with ~2.2 > million rows (~27 seconds on a self_and_ancestors call, set is about > 5 levels deep) > > After a bit of digging I discovered that MySQL was ignoring the > indexes I'd set on the lft & rgt columns when using the BETWEEN > operator. > According to the MySQL docs, between is equivalent to (min <= expr AND > expr <= max) , > after replacing all the instances with this syntax, the query time > went down to ~0.5sec, quite an improvement :) > > This has been working fine for me so far, but it would be great to > hear others opinions on whether this will cause any other problems. > > I've attached a patch if anyone wants to check it out for themselves. > I haven't tested this very extensively apart from in my app, just ran > the unit tests & they all passed (after updating the test_sql_for to > use the same syntax). > I've also only tested this with MySQL 5, so I have no idea how these > changes would effect other databases. > > -- > Lindsay Evans > http://lindsayevans.com/ > > _______________________________________________ > Betternestedset-talk mailing list > Betternestedset-talk at rubyforge.org > http://rubyforge.org/mailman/listinfo/betternestedset-talk > > >