serial in postgres is being increased even though I added on conflict do nothing










9















I'm using Postgres 9.5 and seeing some wired things here.



I've a cron job running ever 5 mins firing a sql statement that is adding a list of records if not existing.



INSERT INTO 
sometable (customer, balance)
VALUES
(:customer, :balance)
ON CONFLICT (customer) DO NOTHING


sometable.customer is a primary key (text)



sometable structure is:

id: serial

customer: text

balance: bigint



Now it seems like everytime this job runs, the id field is silently incremented +1. So next time, I really add a field, it is thousands of numbers above my last value. I thought this query checks for conflicts and if so, do nothing but currently it seems like it tries to insert the record, increased the id and then stops.



Any suggestions?










share|improve this question

















  • 4





    This is by design: postgresql.nabble.com/… But you don't need to worry about those gaps, they are not a problem. The only thing a sequence guarantees is that it never generates the same number twice.

    – a_horse_with_no_name
    May 13 '16 at 8:21






  • 1





    If, for some reason, you actually need a gapless sequence (a rare requirement), then Postgres's SERIAL/SEQUENCE support is not what you should be using. See this answer from Craig Ringer.

    – IMSoP
    May 13 '16 at 9:11















9















I'm using Postgres 9.5 and seeing some wired things here.



I've a cron job running ever 5 mins firing a sql statement that is adding a list of records if not existing.



INSERT INTO 
sometable (customer, balance)
VALUES
(:customer, :balance)
ON CONFLICT (customer) DO NOTHING


sometable.customer is a primary key (text)



sometable structure is:

id: serial

customer: text

balance: bigint



Now it seems like everytime this job runs, the id field is silently incremented +1. So next time, I really add a field, it is thousands of numbers above my last value. I thought this query checks for conflicts and if so, do nothing but currently it seems like it tries to insert the record, increased the id and then stops.



Any suggestions?










share|improve this question

















  • 4





    This is by design: postgresql.nabble.com/… But you don't need to worry about those gaps, they are not a problem. The only thing a sequence guarantees is that it never generates the same number twice.

    – a_horse_with_no_name
    May 13 '16 at 8:21






  • 1





    If, for some reason, you actually need a gapless sequence (a rare requirement), then Postgres's SERIAL/SEQUENCE support is not what you should be using. See this answer from Craig Ringer.

    – IMSoP
    May 13 '16 at 9:11













9












9








9


2






I'm using Postgres 9.5 and seeing some wired things here.



I've a cron job running ever 5 mins firing a sql statement that is adding a list of records if not existing.



INSERT INTO 
sometable (customer, balance)
VALUES
(:customer, :balance)
ON CONFLICT (customer) DO NOTHING


sometable.customer is a primary key (text)



sometable structure is:

id: serial

customer: text

balance: bigint



Now it seems like everytime this job runs, the id field is silently incremented +1. So next time, I really add a field, it is thousands of numbers above my last value. I thought this query checks for conflicts and if so, do nothing but currently it seems like it tries to insert the record, increased the id and then stops.



Any suggestions?










share|improve this question














I'm using Postgres 9.5 and seeing some wired things here.



I've a cron job running ever 5 mins firing a sql statement that is adding a list of records if not existing.



INSERT INTO 
sometable (customer, balance)
VALUES
(:customer, :balance)
ON CONFLICT (customer) DO NOTHING


sometable.customer is a primary key (text)



sometable structure is:

id: serial

customer: text

balance: bigint



Now it seems like everytime this job runs, the id field is silently incremented +1. So next time, I really add a field, it is thousands of numbers above my last value. I thought this query checks for conflicts and if so, do nothing but currently it seems like it tries to insert the record, increased the id and then stops.



Any suggestions?







database postgresql






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked May 13 '16 at 8:15









ChristianChristian

2,60952858




2,60952858







  • 4





    This is by design: postgresql.nabble.com/… But you don't need to worry about those gaps, they are not a problem. The only thing a sequence guarantees is that it never generates the same number twice.

    – a_horse_with_no_name
    May 13 '16 at 8:21






  • 1





    If, for some reason, you actually need a gapless sequence (a rare requirement), then Postgres's SERIAL/SEQUENCE support is not what you should be using. See this answer from Craig Ringer.

    – IMSoP
    May 13 '16 at 9:11












  • 4





    This is by design: postgresql.nabble.com/… But you don't need to worry about those gaps, they are not a problem. The only thing a sequence guarantees is that it never generates the same number twice.

    – a_horse_with_no_name
    May 13 '16 at 8:21






  • 1





    If, for some reason, you actually need a gapless sequence (a rare requirement), then Postgres's SERIAL/SEQUENCE support is not what you should be using. See this answer from Craig Ringer.

    – IMSoP
    May 13 '16 at 9:11







4




4





This is by design: postgresql.nabble.com/… But you don't need to worry about those gaps, they are not a problem. The only thing a sequence guarantees is that it never generates the same number twice.

– a_horse_with_no_name
May 13 '16 at 8:21





This is by design: postgresql.nabble.com/… But you don't need to worry about those gaps, they are not a problem. The only thing a sequence guarantees is that it never generates the same number twice.

– a_horse_with_no_name
May 13 '16 at 8:21




1




1





If, for some reason, you actually need a gapless sequence (a rare requirement), then Postgres's SERIAL/SEQUENCE support is not what you should be using. See this answer from Craig Ringer.

– IMSoP
May 13 '16 at 9:11





If, for some reason, you actually need a gapless sequence (a rare requirement), then Postgres's SERIAL/SEQUENCE support is not what you should be using. See this answer from Craig Ringer.

– IMSoP
May 13 '16 at 9:11












4 Answers
4






active

oldest

votes


















8














The reason this feels weird to you is that you are thinking of the increment on the counter as part of the insert operation, and therefore the "DO NOTHING" ought to mean "don't increment anything". You're picturing this:



  1. Check values to insert against constraint

  2. If duplicate detected, abort

  3. Increment sequence

  4. Insert data

But in fact, the increment has to happen before the insert is attempted. A SERIAL column in Postgres is implemented as a DEFAULT which executes the nextval() function on a bound SEQUENCE. Before the DBMS can do anything with the data, it's got to have a complete set of columns, so the order of operations is like this:



  1. Resolve default values, including incrementing the sequence

  2. Check values to insert against constraint

  3. If duplicate detected, abort

  4. Insert data

This can be seen intuitively if the duplicate key is in the autoincrement field itself:



CREATE TABLE foo ( id SERIAL NOT NULL PRIMARY KEY, bar text );
-- Insert row 1
INSERT INTO foo ( bar ) VALUES ( 'test' );
-- Reset the sequence
SELECT setval(pg_get_serial_sequence('foo', 'id'), 0, true);
-- Attempt to insert row 1 again
INSERT INTO foo ( bar ) VALUES ( 'test 2' )
ON CONFLICT (id) DO NOTHING;


Clearly, this can't know if there's a conflict without incrementing the sequence, so the "do nothing" has to come after that increment.






share|improve this answer






























    2














    As already said by @a_horse_with_no_name and @Serge Ballesta serials are always incremented even if INSERT fails.



    You can try to "rollback" serial value to maximum id used by changing the corresponding sequence:



    SELECT setval('sometable_id_seq', MAX(id), true) FROM sometable;





    share|improve this answer


















    • 1





      Note that passing true as the third parameter to setval is the same as not passing a third parameter. setval('sometable_id_seq', MAX(id), true) is equivalent to setval('sometable_id_seq', MAX(id))

      – BrDaHa
      May 24 '17 at 21:07


















    1














    As said by @a_horse_with_no_name, that is by design. Serial type fields are implemented under the hood through sequences, and for evident reasons, once you have gotten a new value from a sequence, you cannot rollback the last value. Imagine the following scenario:



    • sequence is at n

    • A requires a new value : got n+1

    • in a concurrent transaction B requires a new value: got n+2

    • for any reason A rollbacks its transaction - would you feel safe to reset sequence?

    That is the reason why sequences (and serial field) just document that in case of rollbacked transactions holes can occur in the returned values. Only unicity is guaranteed.






    share|improve this answer


















    • 1





      Yeah thanks I got that, but in my point of view a +1 doesn't make sense if do nothing is provided at the query. if should check before actually adding whether it needs to add anything. Also I am worried about the gaps. This job runs every 5 mins...

      – Christian
      May 13 '16 at 8:40






    • 1





      so only thing I can do is actually check by myself whether it's needed to add this record by selecting all of them :-/

      – Christian
      May 13 '16 at 8:41






    • 1





      @Christian: there is nothing you need to do. Just ignore the gaps. There is nothing wrong with ID values having (large gaps)

      – a_horse_with_no_name
      May 13 '16 at 8:43







    • 2





      @a_horse_with_no_name Unless you are inserting enough data to overflow a SERIAL in a "short" (purposefully vague) amount of time. I was going to do this for a query that runs ~50 times/second, but I would run out of unique values in roughly 1.36 years. I wish instead of being forced to use BIGSERIAL there was a command like SELECT id FROM table WHERE uniqueCol = 'val' ON EMPTY INSERT INTO table (uniqueCol) VALUES ('val') ON CONFLICT(uniqueCol) DO UPDATE SET uniqueCol = EXCLUDED.uniqueCol RETURNING id. That would significantly reduce the number of wasted id's.

      – Jeff G
      Oct 11 '16 at 0:12


















    -1














    Well there is technique that allows you to do stuff like that. They call insert mutex. It is old old old, but it works.



    https://www.percona.com/blog/2011/11/29/avoiding-auto-increment-holes-on-innodb-with-insert-ignore/



    Generally idea is that you do INSERT SELECT and if your values are duplicating the SELECT does not return any results that of course prevents INSERT and the index is not incremented. Bit of mind boggling, but perfectly valid and performant.



    This of course completely ignores ON DUPLICATE but one gets back control over the index.






    share|improve this answer
























      Your Answer






      StackExchange.ifUsing("editor", function ()
      StackExchange.using("externalEditor", function ()
      StackExchange.using("snippets", function ()
      StackExchange.snippets.init();
      );
      );
      , "code-snippets");

      StackExchange.ready(function()
      var channelOptions =
      tags: "".split(" "),
      id: "1"
      ;
      initTagRenderer("".split(" "), "".split(" "), channelOptions);

      StackExchange.using("externalEditor", function()
      // Have to fire editor after snippets, if snippets enabled
      if (StackExchange.settings.snippets.snippetsEnabled)
      StackExchange.using("snippets", function()
      createEditor();
      );

      else
      createEditor();

      );

      function createEditor()
      StackExchange.prepareEditor(
      heartbeatType: 'answer',
      autoActivateHeartbeat: false,
      convertImagesToLinks: true,
      noModals: true,
      showLowRepImageUploadWarning: true,
      reputationToPostImages: 10,
      bindNavPrevention: true,
      postfix: "",
      imageUploader:
      brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
      contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
      allowUrls: true
      ,
      onDemand: true,
      discardSelector: ".discard-answer"
      ,immediatelyShowMarkdownHelp:true
      );



      );













      draft saved

      draft discarded


















      StackExchange.ready(
      function ()
      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f37204749%2fserial-in-postgres-is-being-increased-even-though-i-added-on-conflict-do-nothing%23new-answer', 'question_page');

      );

      Post as a guest















      Required, but never shown

























      4 Answers
      4






      active

      oldest

      votes








      4 Answers
      4






      active

      oldest

      votes









      active

      oldest

      votes






      active

      oldest

      votes









      8














      The reason this feels weird to you is that you are thinking of the increment on the counter as part of the insert operation, and therefore the "DO NOTHING" ought to mean "don't increment anything". You're picturing this:



      1. Check values to insert against constraint

      2. If duplicate detected, abort

      3. Increment sequence

      4. Insert data

      But in fact, the increment has to happen before the insert is attempted. A SERIAL column in Postgres is implemented as a DEFAULT which executes the nextval() function on a bound SEQUENCE. Before the DBMS can do anything with the data, it's got to have a complete set of columns, so the order of operations is like this:



      1. Resolve default values, including incrementing the sequence

      2. Check values to insert against constraint

      3. If duplicate detected, abort

      4. Insert data

      This can be seen intuitively if the duplicate key is in the autoincrement field itself:



      CREATE TABLE foo ( id SERIAL NOT NULL PRIMARY KEY, bar text );
      -- Insert row 1
      INSERT INTO foo ( bar ) VALUES ( 'test' );
      -- Reset the sequence
      SELECT setval(pg_get_serial_sequence('foo', 'id'), 0, true);
      -- Attempt to insert row 1 again
      INSERT INTO foo ( bar ) VALUES ( 'test 2' )
      ON CONFLICT (id) DO NOTHING;


      Clearly, this can't know if there's a conflict without incrementing the sequence, so the "do nothing" has to come after that increment.






      share|improve this answer



























        8














        The reason this feels weird to you is that you are thinking of the increment on the counter as part of the insert operation, and therefore the "DO NOTHING" ought to mean "don't increment anything". You're picturing this:



        1. Check values to insert against constraint

        2. If duplicate detected, abort

        3. Increment sequence

        4. Insert data

        But in fact, the increment has to happen before the insert is attempted. A SERIAL column in Postgres is implemented as a DEFAULT which executes the nextval() function on a bound SEQUENCE. Before the DBMS can do anything with the data, it's got to have a complete set of columns, so the order of operations is like this:



        1. Resolve default values, including incrementing the sequence

        2. Check values to insert against constraint

        3. If duplicate detected, abort

        4. Insert data

        This can be seen intuitively if the duplicate key is in the autoincrement field itself:



        CREATE TABLE foo ( id SERIAL NOT NULL PRIMARY KEY, bar text );
        -- Insert row 1
        INSERT INTO foo ( bar ) VALUES ( 'test' );
        -- Reset the sequence
        SELECT setval(pg_get_serial_sequence('foo', 'id'), 0, true);
        -- Attempt to insert row 1 again
        INSERT INTO foo ( bar ) VALUES ( 'test 2' )
        ON CONFLICT (id) DO NOTHING;


        Clearly, this can't know if there's a conflict without incrementing the sequence, so the "do nothing" has to come after that increment.






        share|improve this answer

























          8












          8








          8







          The reason this feels weird to you is that you are thinking of the increment on the counter as part of the insert operation, and therefore the "DO NOTHING" ought to mean "don't increment anything". You're picturing this:



          1. Check values to insert against constraint

          2. If duplicate detected, abort

          3. Increment sequence

          4. Insert data

          But in fact, the increment has to happen before the insert is attempted. A SERIAL column in Postgres is implemented as a DEFAULT which executes the nextval() function on a bound SEQUENCE. Before the DBMS can do anything with the data, it's got to have a complete set of columns, so the order of operations is like this:



          1. Resolve default values, including incrementing the sequence

          2. Check values to insert against constraint

          3. If duplicate detected, abort

          4. Insert data

          This can be seen intuitively if the duplicate key is in the autoincrement field itself:



          CREATE TABLE foo ( id SERIAL NOT NULL PRIMARY KEY, bar text );
          -- Insert row 1
          INSERT INTO foo ( bar ) VALUES ( 'test' );
          -- Reset the sequence
          SELECT setval(pg_get_serial_sequence('foo', 'id'), 0, true);
          -- Attempt to insert row 1 again
          INSERT INTO foo ( bar ) VALUES ( 'test 2' )
          ON CONFLICT (id) DO NOTHING;


          Clearly, this can't know if there's a conflict without incrementing the sequence, so the "do nothing" has to come after that increment.






          share|improve this answer













          The reason this feels weird to you is that you are thinking of the increment on the counter as part of the insert operation, and therefore the "DO NOTHING" ought to mean "don't increment anything". You're picturing this:



          1. Check values to insert against constraint

          2. If duplicate detected, abort

          3. Increment sequence

          4. Insert data

          But in fact, the increment has to happen before the insert is attempted. A SERIAL column in Postgres is implemented as a DEFAULT which executes the nextval() function on a bound SEQUENCE. Before the DBMS can do anything with the data, it's got to have a complete set of columns, so the order of operations is like this:



          1. Resolve default values, including incrementing the sequence

          2. Check values to insert against constraint

          3. If duplicate detected, abort

          4. Insert data

          This can be seen intuitively if the duplicate key is in the autoincrement field itself:



          CREATE TABLE foo ( id SERIAL NOT NULL PRIMARY KEY, bar text );
          -- Insert row 1
          INSERT INTO foo ( bar ) VALUES ( 'test' );
          -- Reset the sequence
          SELECT setval(pg_get_serial_sequence('foo', 'id'), 0, true);
          -- Attempt to insert row 1 again
          INSERT INTO foo ( bar ) VALUES ( 'test 2' )
          ON CONFLICT (id) DO NOTHING;


          Clearly, this can't know if there's a conflict without incrementing the sequence, so the "do nothing" has to come after that increment.







          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered May 13 '16 at 9:24









          IMSoPIMSoP

          46k65693




          46k65693























              2














              As already said by @a_horse_with_no_name and @Serge Ballesta serials are always incremented even if INSERT fails.



              You can try to "rollback" serial value to maximum id used by changing the corresponding sequence:



              SELECT setval('sometable_id_seq', MAX(id), true) FROM sometable;





              share|improve this answer


















              • 1





                Note that passing true as the third parameter to setval is the same as not passing a third parameter. setval('sometable_id_seq', MAX(id), true) is equivalent to setval('sometable_id_seq', MAX(id))

                – BrDaHa
                May 24 '17 at 21:07















              2














              As already said by @a_horse_with_no_name and @Serge Ballesta serials are always incremented even if INSERT fails.



              You can try to "rollback" serial value to maximum id used by changing the corresponding sequence:



              SELECT setval('sometable_id_seq', MAX(id), true) FROM sometable;





              share|improve this answer


















              • 1





                Note that passing true as the third parameter to setval is the same as not passing a third parameter. setval('sometable_id_seq', MAX(id), true) is equivalent to setval('sometable_id_seq', MAX(id))

                – BrDaHa
                May 24 '17 at 21:07













              2












              2








              2







              As already said by @a_horse_with_no_name and @Serge Ballesta serials are always incremented even if INSERT fails.



              You can try to "rollback" serial value to maximum id used by changing the corresponding sequence:



              SELECT setval('sometable_id_seq', MAX(id), true) FROM sometable;





              share|improve this answer













              As already said by @a_horse_with_no_name and @Serge Ballesta serials are always incremented even if INSERT fails.



              You can try to "rollback" serial value to maximum id used by changing the corresponding sequence:



              SELECT setval('sometable_id_seq', MAX(id), true) FROM sometable;






              share|improve this answer












              share|improve this answer



              share|improve this answer










              answered May 13 '16 at 8:39









              AdamAdam

              3,83262030




              3,83262030







              • 1





                Note that passing true as the third parameter to setval is the same as not passing a third parameter. setval('sometable_id_seq', MAX(id), true) is equivalent to setval('sometable_id_seq', MAX(id))

                – BrDaHa
                May 24 '17 at 21:07












              • 1





                Note that passing true as the third parameter to setval is the same as not passing a third parameter. setval('sometable_id_seq', MAX(id), true) is equivalent to setval('sometable_id_seq', MAX(id))

                – BrDaHa
                May 24 '17 at 21:07







              1




              1





              Note that passing true as the third parameter to setval is the same as not passing a third parameter. setval('sometable_id_seq', MAX(id), true) is equivalent to setval('sometable_id_seq', MAX(id))

              – BrDaHa
              May 24 '17 at 21:07





              Note that passing true as the third parameter to setval is the same as not passing a third parameter. setval('sometable_id_seq', MAX(id), true) is equivalent to setval('sometable_id_seq', MAX(id))

              – BrDaHa
              May 24 '17 at 21:07











              1














              As said by @a_horse_with_no_name, that is by design. Serial type fields are implemented under the hood through sequences, and for evident reasons, once you have gotten a new value from a sequence, you cannot rollback the last value. Imagine the following scenario:



              • sequence is at n

              • A requires a new value : got n+1

              • in a concurrent transaction B requires a new value: got n+2

              • for any reason A rollbacks its transaction - would you feel safe to reset sequence?

              That is the reason why sequences (and serial field) just document that in case of rollbacked transactions holes can occur in the returned values. Only unicity is guaranteed.






              share|improve this answer


















              • 1





                Yeah thanks I got that, but in my point of view a +1 doesn't make sense if do nothing is provided at the query. if should check before actually adding whether it needs to add anything. Also I am worried about the gaps. This job runs every 5 mins...

                – Christian
                May 13 '16 at 8:40






              • 1





                so only thing I can do is actually check by myself whether it's needed to add this record by selecting all of them :-/

                – Christian
                May 13 '16 at 8:41






              • 1





                @Christian: there is nothing you need to do. Just ignore the gaps. There is nothing wrong with ID values having (large gaps)

                – a_horse_with_no_name
                May 13 '16 at 8:43







              • 2





                @a_horse_with_no_name Unless you are inserting enough data to overflow a SERIAL in a "short" (purposefully vague) amount of time. I was going to do this for a query that runs ~50 times/second, but I would run out of unique values in roughly 1.36 years. I wish instead of being forced to use BIGSERIAL there was a command like SELECT id FROM table WHERE uniqueCol = 'val' ON EMPTY INSERT INTO table (uniqueCol) VALUES ('val') ON CONFLICT(uniqueCol) DO UPDATE SET uniqueCol = EXCLUDED.uniqueCol RETURNING id. That would significantly reduce the number of wasted id's.

                – Jeff G
                Oct 11 '16 at 0:12















              1














              As said by @a_horse_with_no_name, that is by design. Serial type fields are implemented under the hood through sequences, and for evident reasons, once you have gotten a new value from a sequence, you cannot rollback the last value. Imagine the following scenario:



              • sequence is at n

              • A requires a new value : got n+1

              • in a concurrent transaction B requires a new value: got n+2

              • for any reason A rollbacks its transaction - would you feel safe to reset sequence?

              That is the reason why sequences (and serial field) just document that in case of rollbacked transactions holes can occur in the returned values. Only unicity is guaranteed.






              share|improve this answer


















              • 1





                Yeah thanks I got that, but in my point of view a +1 doesn't make sense if do nothing is provided at the query. if should check before actually adding whether it needs to add anything. Also I am worried about the gaps. This job runs every 5 mins...

                – Christian
                May 13 '16 at 8:40






              • 1





                so only thing I can do is actually check by myself whether it's needed to add this record by selecting all of them :-/

                – Christian
                May 13 '16 at 8:41






              • 1





                @Christian: there is nothing you need to do. Just ignore the gaps. There is nothing wrong with ID values having (large gaps)

                – a_horse_with_no_name
                May 13 '16 at 8:43







              • 2





                @a_horse_with_no_name Unless you are inserting enough data to overflow a SERIAL in a "short" (purposefully vague) amount of time. I was going to do this for a query that runs ~50 times/second, but I would run out of unique values in roughly 1.36 years. I wish instead of being forced to use BIGSERIAL there was a command like SELECT id FROM table WHERE uniqueCol = 'val' ON EMPTY INSERT INTO table (uniqueCol) VALUES ('val') ON CONFLICT(uniqueCol) DO UPDATE SET uniqueCol = EXCLUDED.uniqueCol RETURNING id. That would significantly reduce the number of wasted id's.

                – Jeff G
                Oct 11 '16 at 0:12













              1












              1








              1







              As said by @a_horse_with_no_name, that is by design. Serial type fields are implemented under the hood through sequences, and for evident reasons, once you have gotten a new value from a sequence, you cannot rollback the last value. Imagine the following scenario:



              • sequence is at n

              • A requires a new value : got n+1

              • in a concurrent transaction B requires a new value: got n+2

              • for any reason A rollbacks its transaction - would you feel safe to reset sequence?

              That is the reason why sequences (and serial field) just document that in case of rollbacked transactions holes can occur in the returned values. Only unicity is guaranteed.






              share|improve this answer













              As said by @a_horse_with_no_name, that is by design. Serial type fields are implemented under the hood through sequences, and for evident reasons, once you have gotten a new value from a sequence, you cannot rollback the last value. Imagine the following scenario:



              • sequence is at n

              • A requires a new value : got n+1

              • in a concurrent transaction B requires a new value: got n+2

              • for any reason A rollbacks its transaction - would you feel safe to reset sequence?

              That is the reason why sequences (and serial field) just document that in case of rollbacked transactions holes can occur in the returned values. Only unicity is guaranteed.







              share|improve this answer












              share|improve this answer



              share|improve this answer










              answered May 13 '16 at 8:28









              Serge BallestaSerge Ballesta

              76.4k956130




              76.4k956130







              • 1





                Yeah thanks I got that, but in my point of view a +1 doesn't make sense if do nothing is provided at the query. if should check before actually adding whether it needs to add anything. Also I am worried about the gaps. This job runs every 5 mins...

                – Christian
                May 13 '16 at 8:40






              • 1





                so only thing I can do is actually check by myself whether it's needed to add this record by selecting all of them :-/

                – Christian
                May 13 '16 at 8:41






              • 1





                @Christian: there is nothing you need to do. Just ignore the gaps. There is nothing wrong with ID values having (large gaps)

                – a_horse_with_no_name
                May 13 '16 at 8:43







              • 2





                @a_horse_with_no_name Unless you are inserting enough data to overflow a SERIAL in a "short" (purposefully vague) amount of time. I was going to do this for a query that runs ~50 times/second, but I would run out of unique values in roughly 1.36 years. I wish instead of being forced to use BIGSERIAL there was a command like SELECT id FROM table WHERE uniqueCol = 'val' ON EMPTY INSERT INTO table (uniqueCol) VALUES ('val') ON CONFLICT(uniqueCol) DO UPDATE SET uniqueCol = EXCLUDED.uniqueCol RETURNING id. That would significantly reduce the number of wasted id's.

                – Jeff G
                Oct 11 '16 at 0:12












              • 1





                Yeah thanks I got that, but in my point of view a +1 doesn't make sense if do nothing is provided at the query. if should check before actually adding whether it needs to add anything. Also I am worried about the gaps. This job runs every 5 mins...

                – Christian
                May 13 '16 at 8:40






              • 1





                so only thing I can do is actually check by myself whether it's needed to add this record by selecting all of them :-/

                – Christian
                May 13 '16 at 8:41






              • 1





                @Christian: there is nothing you need to do. Just ignore the gaps. There is nothing wrong with ID values having (large gaps)

                – a_horse_with_no_name
                May 13 '16 at 8:43







              • 2





                @a_horse_with_no_name Unless you are inserting enough data to overflow a SERIAL in a "short" (purposefully vague) amount of time. I was going to do this for a query that runs ~50 times/second, but I would run out of unique values in roughly 1.36 years. I wish instead of being forced to use BIGSERIAL there was a command like SELECT id FROM table WHERE uniqueCol = 'val' ON EMPTY INSERT INTO table (uniqueCol) VALUES ('val') ON CONFLICT(uniqueCol) DO UPDATE SET uniqueCol = EXCLUDED.uniqueCol RETURNING id. That would significantly reduce the number of wasted id's.

                – Jeff G
                Oct 11 '16 at 0:12







              1




              1





              Yeah thanks I got that, but in my point of view a +1 doesn't make sense if do nothing is provided at the query. if should check before actually adding whether it needs to add anything. Also I am worried about the gaps. This job runs every 5 mins...

              – Christian
              May 13 '16 at 8:40





              Yeah thanks I got that, but in my point of view a +1 doesn't make sense if do nothing is provided at the query. if should check before actually adding whether it needs to add anything. Also I am worried about the gaps. This job runs every 5 mins...

              – Christian
              May 13 '16 at 8:40




              1




              1





              so only thing I can do is actually check by myself whether it's needed to add this record by selecting all of them :-/

              – Christian
              May 13 '16 at 8:41





              so only thing I can do is actually check by myself whether it's needed to add this record by selecting all of them :-/

              – Christian
              May 13 '16 at 8:41




              1




              1





              @Christian: there is nothing you need to do. Just ignore the gaps. There is nothing wrong with ID values having (large gaps)

              – a_horse_with_no_name
              May 13 '16 at 8:43






              @Christian: there is nothing you need to do. Just ignore the gaps. There is nothing wrong with ID values having (large gaps)

              – a_horse_with_no_name
              May 13 '16 at 8:43





              2




              2





              @a_horse_with_no_name Unless you are inserting enough data to overflow a SERIAL in a "short" (purposefully vague) amount of time. I was going to do this for a query that runs ~50 times/second, but I would run out of unique values in roughly 1.36 years. I wish instead of being forced to use BIGSERIAL there was a command like SELECT id FROM table WHERE uniqueCol = 'val' ON EMPTY INSERT INTO table (uniqueCol) VALUES ('val') ON CONFLICT(uniqueCol) DO UPDATE SET uniqueCol = EXCLUDED.uniqueCol RETURNING id. That would significantly reduce the number of wasted id's.

              – Jeff G
              Oct 11 '16 at 0:12





              @a_horse_with_no_name Unless you are inserting enough data to overflow a SERIAL in a "short" (purposefully vague) amount of time. I was going to do this for a query that runs ~50 times/second, but I would run out of unique values in roughly 1.36 years. I wish instead of being forced to use BIGSERIAL there was a command like SELECT id FROM table WHERE uniqueCol = 'val' ON EMPTY INSERT INTO table (uniqueCol) VALUES ('val') ON CONFLICT(uniqueCol) DO UPDATE SET uniqueCol = EXCLUDED.uniqueCol RETURNING id. That would significantly reduce the number of wasted id's.

              – Jeff G
              Oct 11 '16 at 0:12











              -1














              Well there is technique that allows you to do stuff like that. They call insert mutex. It is old old old, but it works.



              https://www.percona.com/blog/2011/11/29/avoiding-auto-increment-holes-on-innodb-with-insert-ignore/



              Generally idea is that you do INSERT SELECT and if your values are duplicating the SELECT does not return any results that of course prevents INSERT and the index is not incremented. Bit of mind boggling, but perfectly valid and performant.



              This of course completely ignores ON DUPLICATE but one gets back control over the index.






              share|improve this answer





























                -1














                Well there is technique that allows you to do stuff like that. They call insert mutex. It is old old old, but it works.



                https://www.percona.com/blog/2011/11/29/avoiding-auto-increment-holes-on-innodb-with-insert-ignore/



                Generally idea is that you do INSERT SELECT and if your values are duplicating the SELECT does not return any results that of course prevents INSERT and the index is not incremented. Bit of mind boggling, but perfectly valid and performant.



                This of course completely ignores ON DUPLICATE but one gets back control over the index.






                share|improve this answer



























                  -1












                  -1








                  -1







                  Well there is technique that allows you to do stuff like that. They call insert mutex. It is old old old, but it works.



                  https://www.percona.com/blog/2011/11/29/avoiding-auto-increment-holes-on-innodb-with-insert-ignore/



                  Generally idea is that you do INSERT SELECT and if your values are duplicating the SELECT does not return any results that of course prevents INSERT and the index is not incremented. Bit of mind boggling, but perfectly valid and performant.



                  This of course completely ignores ON DUPLICATE but one gets back control over the index.






                  share|improve this answer















                  Well there is technique that allows you to do stuff like that. They call insert mutex. It is old old old, but it works.



                  https://www.percona.com/blog/2011/11/29/avoiding-auto-increment-holes-on-innodb-with-insert-ignore/



                  Generally idea is that you do INSERT SELECT and if your values are duplicating the SELECT does not return any results that of course prevents INSERT and the index is not incremented. Bit of mind boggling, but perfectly valid and performant.



                  This of course completely ignores ON DUPLICATE but one gets back control over the index.







                  share|improve this answer














                  share|improve this answer



                  share|improve this answer








                  edited Jul 26 '18 at 16:29

























                  answered Jul 26 '18 at 16:24









                  sp3c1sp3c1

                  45045




                  45045



























                      draft saved

                      draft discarded
















































                      Thanks for contributing an answer to Stack Overflow!


                      • Please be sure to answer the question. Provide details and share your research!

                      But avoid


                      • Asking for help, clarification, or responding to other answers.

                      • Making statements based on opinion; back them up with references or personal experience.

                      To learn more, see our tips on writing great answers.




                      draft saved


                      draft discarded














                      StackExchange.ready(
                      function ()
                      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f37204749%2fserial-in-postgres-is-being-increased-even-though-i-added-on-conflict-do-nothing%23new-answer', 'question_page');

                      );

                      Post as a guest















                      Required, but never shown





















































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown

































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown







                      Popular posts from this blog

                      Use pre created SQLite database for Android project in kotlin

                      Darth Vader #20

                      Ondo