Should I defragment InnoDB table with fixed-length fields?What is the difference between optimize table and...

Is layered encryption more secure than long passwords?

If I tried and failed to start my own business, how do I apply for a job without job experience?

Is it possible to detect 100% of SQLi with a simple regex?

Problems with position of tikzpictures in beamer

How can I keep my gold safe from other PCs?

Isn't a semicolon (';') needed after a function declaration in C++?

Is practicing on a digital piano harmful to an experienced piano player?

Is the UK legally prevented from having another referendum on Brexit?

In the Lost in Space intro why was Dr. Smith actor listed as a special guest star?

Sets that are both Sum-free and Product-free

Coworker is trying to get me to sign his petition to run for office. How to decline politely?

How can I give a Ranger advantage on a check due to Favored Enemy without spoiling the story for the player?

Why does a single AND gate need 60 transistors?

Is it possible to narrate a novel in a faux-historical style without alienating the reader?

Including proofs of known theorems in master's thesis

If we can’t finish all tasks, does this mean we are doing Scrum wrong?

Why don't you get burned by the wood benches in a sauna?

How to regain lost focus?

How to deal with an underperforming subordinate?

What is the meaning of "usr"?

How do I purchase a drop bar bike that will be converted to flat bar?

Is having explosions as a go-to solution considered bad table manners?

Coworker asking me to not bring cakes due to self control issue. What should I do?

Could a civilization in medieval fantasy world sustain itself by occupying important trade hubs and taxing trade?



Should I defragment InnoDB table with fixed-length fields?


What is the difference between optimize table and analyze table in mysqlAre two indexes needed?Finding rows for a specified date rangeCalculating employee's work timeAdding index to large mysql tablesWhy are simple SELECTs on InnoDB 100x slower than on MyISAM?Updating a table with a single UPDATE statement vs several UPDATE statementsOptimizing a simple query on a large tableHow to improve query count execution with mySql replicate?Deadlocks appeared after moving to MariaDB10.2 from MySQL5.5Why does the Select statement stalls when executed directly in sequence?













1















I am running MariaDB 10.2.13 on Linux (Debian).



I am setting up an InnoDB table that will record a lot of data but I will keep only the last one-hour rows. Thus, the number of rows will remain constant.



I should expect on this table:




  • many INSERTs

  • many UPDATEs

  • some DELETE (rows > 1 hour) from time to time


Example:



Table is defined with fixed-length fields only and some indexes.



CREATE TABLE `tbl_log` (
`ip` int(4) unsigned NOT NULL,
`date` datetime NOT NULL,
`external_id` smallint(6) unsigned NOT NULL,
`counter` smallint(6) unsigned NOT NULL DEFAULT 0,
PRIMARY KEY (`ip`,`external_id`),
KEY `external_id` (`external_id`),
KEY `counter` (`counter`),
KEY `date_idx` (`date`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;


Inserts (and updates, through on duplicate key) may look like this (ip and external_id will vary):



INSERT INTO tbl_log
SET ip = INET_ATON('192.168.1.1'),
date = now(),
external_id = 123,
counter = 0
ON DUPLICATE KEY UPDATE counter=counter+1;


Finally, deleting old rows will be done with a query:



DELETE FROM tbl_log WHERE date < DATE_SUB(NOW(), INTERVAL 1 HOUR);


Question:



Will such a table fragment over time?



If so, I think I should defragment it. If necessary, I planned to run OPTIMIZE TABLE tbl_log; (with option innodb-defragment=1) right after delete...










share|improve this question
















bumped to the homepage by Community 1 min ago


This question has answers that may be good or bad; the system has marked it active so that they can be reviewed.




















    1















    I am running MariaDB 10.2.13 on Linux (Debian).



    I am setting up an InnoDB table that will record a lot of data but I will keep only the last one-hour rows. Thus, the number of rows will remain constant.



    I should expect on this table:




    • many INSERTs

    • many UPDATEs

    • some DELETE (rows > 1 hour) from time to time


    Example:



    Table is defined with fixed-length fields only and some indexes.



    CREATE TABLE `tbl_log` (
    `ip` int(4) unsigned NOT NULL,
    `date` datetime NOT NULL,
    `external_id` smallint(6) unsigned NOT NULL,
    `counter` smallint(6) unsigned NOT NULL DEFAULT 0,
    PRIMARY KEY (`ip`,`external_id`),
    KEY `external_id` (`external_id`),
    KEY `counter` (`counter`),
    KEY `date_idx` (`date`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;


    Inserts (and updates, through on duplicate key) may look like this (ip and external_id will vary):



    INSERT INTO tbl_log
    SET ip = INET_ATON('192.168.1.1'),
    date = now(),
    external_id = 123,
    counter = 0
    ON DUPLICATE KEY UPDATE counter=counter+1;


    Finally, deleting old rows will be done with a query:



    DELETE FROM tbl_log WHERE date < DATE_SUB(NOW(), INTERVAL 1 HOUR);


    Question:



    Will such a table fragment over time?



    If so, I think I should defragment it. If necessary, I planned to run OPTIMIZE TABLE tbl_log; (with option innodb-defragment=1) right after delete...










    share|improve this question
















    bumped to the homepage by Community 1 min ago


    This question has answers that may be good or bad; the system has marked it active so that they can be reviewed.


















      1












      1








      1








      I am running MariaDB 10.2.13 on Linux (Debian).



      I am setting up an InnoDB table that will record a lot of data but I will keep only the last one-hour rows. Thus, the number of rows will remain constant.



      I should expect on this table:




      • many INSERTs

      • many UPDATEs

      • some DELETE (rows > 1 hour) from time to time


      Example:



      Table is defined with fixed-length fields only and some indexes.



      CREATE TABLE `tbl_log` (
      `ip` int(4) unsigned NOT NULL,
      `date` datetime NOT NULL,
      `external_id` smallint(6) unsigned NOT NULL,
      `counter` smallint(6) unsigned NOT NULL DEFAULT 0,
      PRIMARY KEY (`ip`,`external_id`),
      KEY `external_id` (`external_id`),
      KEY `counter` (`counter`),
      KEY `date_idx` (`date`)
      ) ENGINE=InnoDB DEFAULT CHARSET=utf8;


      Inserts (and updates, through on duplicate key) may look like this (ip and external_id will vary):



      INSERT INTO tbl_log
      SET ip = INET_ATON('192.168.1.1'),
      date = now(),
      external_id = 123,
      counter = 0
      ON DUPLICATE KEY UPDATE counter=counter+1;


      Finally, deleting old rows will be done with a query:



      DELETE FROM tbl_log WHERE date < DATE_SUB(NOW(), INTERVAL 1 HOUR);


      Question:



      Will such a table fragment over time?



      If so, I think I should defragment it. If necessary, I planned to run OPTIMIZE TABLE tbl_log; (with option innodb-defragment=1) right after delete...










      share|improve this question
















      I am running MariaDB 10.2.13 on Linux (Debian).



      I am setting up an InnoDB table that will record a lot of data but I will keep only the last one-hour rows. Thus, the number of rows will remain constant.



      I should expect on this table:




      • many INSERTs

      • many UPDATEs

      • some DELETE (rows > 1 hour) from time to time


      Example:



      Table is defined with fixed-length fields only and some indexes.



      CREATE TABLE `tbl_log` (
      `ip` int(4) unsigned NOT NULL,
      `date` datetime NOT NULL,
      `external_id` smallint(6) unsigned NOT NULL,
      `counter` smallint(6) unsigned NOT NULL DEFAULT 0,
      PRIMARY KEY (`ip`,`external_id`),
      KEY `external_id` (`external_id`),
      KEY `counter` (`counter`),
      KEY `date_idx` (`date`)
      ) ENGINE=InnoDB DEFAULT CHARSET=utf8;


      Inserts (and updates, through on duplicate key) may look like this (ip and external_id will vary):



      INSERT INTO tbl_log
      SET ip = INET_ATON('192.168.1.1'),
      date = now(),
      external_id = 123,
      counter = 0
      ON DUPLICATE KEY UPDATE counter=counter+1;


      Finally, deleting old rows will be done with a query:



      DELETE FROM tbl_log WHERE date < DATE_SUB(NOW(), INTERVAL 1 HOUR);


      Question:



      Will such a table fragment over time?



      If so, I think I should defragment it. If necessary, I planned to run OPTIMIZE TABLE tbl_log; (with option innodb-defragment=1) right after delete...







      mysql innodb mariadb fragmentation






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Mar 20 '18 at 16:44









      RolandoMySQLDBA

      142k24223379




      142k24223379










      asked Mar 20 '18 at 14:35









      Nicolas PayartNicolas Payart

      69531127




      69531127





      bumped to the homepage by Community 1 min ago


      This question has answers that may be good or bad; the system has marked it active so that they can be reviewed.







      bumped to the homepage by Community 1 min ago


      This question has answers that may be good or bad; the system has marked it active so that they can be reviewed.
























          2 Answers
          2






          active

          oldest

          votes


















          0














          I would say yes for four(4) major reasons




          1. Page Boundaries / Index Pages

          2. Index Layout

          3. Index Statistics

          4. Bulk DML


          PAGE BOUNDARIES / INDEX PAGES



          According to the MySQL Documentation on Limits on InnoDB tables




          The maximum row length, except for variable-length columns (VARBINARY, VARCHAR, BLOB and TEXT), is slightly less than half of a page for 4KB, 8KB, 16KB, and 32KB page sizes. For example, the maximum row length for the default innodb_page_size of 16KB is about 8000 bytes. For an InnoDB page size of 64KB, the maximum row length is about 16000 bytes. LONGBLOB and LONGTEXT columns must be less than 4GB, and the total row length, including BLOB and TEXT columns, must be less than 4GB.




          Your table uses INT UNSIGNED (4 bytes), DATETIME (8 bytes), 2 SMALLINTs (4 bytes) per row. That's a total of 16 bytes per row. This means you can fit 1000 rows into a single InnoDB page, but there is a very small piece of fragmentation. Using the default innodb_page_size (16K or 16384), there will be 384 bytes of fragmentation with a page. It is most likely used for mapping the data within the one page.



          Doing mass INSERTs, DELETEs, and UPDATEs will generate many pages with empty space for whole rows that are marked as unused. This is in addition to the 384 bytes region of the data page.



          INDEX LAYOUT



          You will generate many index pages




          • You have a 6-byte PRIMARY KEY

          • Each secondary index carries a copy of the PRIMARY KEY


          • KEY external_id (external_id), will be 8 bytes (SMALLINT + PRIMARY KEY)


          • KEY counter (counter), will be 8 bytes (SMALLINT + PRIMARY KEY)


          • KEY date_idx (date) will be 14 bytes (DATE + PRIMARY KEY)

          • 36 bytes for indexing a single row

          • Indexes are represented as BTREEs, so you are looking at O(n log n) space utilization. If you account for non-leaf page splits, many index pages will be 50% empty (without question).


          INDEX STATISTICS



          Running INSERTs, DELETEs, and UPDATEs will skew index stats since index cardinalities will frequently change. You need to run ANALYZE TABLE tbl_log;. Running OPTIMIZE TABLE tbl_log; will defrag the tables and run ANALYZE TABLE tbl_log; as the last step (See my post from Feb 27, 2013 : What is the difference between optimize table and analyze table in mysql)



          BULK DML



          The DELETE query you will be doing by the hour is a bulk operation. Many rows will need a ton of housecleaning to keep up with marking rows deleted.






          share|improve this answer
























          • No, you can't hold 1000 rows per page. There is per-column, per-row, and per-block overheads. You'll be lucky to get 500 rows/block.

            – Rick James
            Mar 23 '18 at 0:55











          • DATETIME is no longer 8 bytes, but only 5 in newer versions.

            – Rick James
            Mar 23 '18 at 0:57











          • The PK is 9 bytes, not 6. Hence, all the math about secondary keys is off. Plus there is overhead in secondary key BTrees.

            – Rick James
            Mar 23 '18 at 0:57













          • Block splits lead to the BTree being an average of 69% full. This is not bad, and should be ignored.

            – Rick James
            Mar 23 '18 at 1:00



















          0














          I say "no" for various reasons.




          • The fragmentation will recur promptly after the OPTIMIZE, so why bother.

          • The fragmentation is not that big a deal. The performance issue is minimal. The "depth" of the BTrees rarely changes due to fragmentation.

          • InnoDB tends to get rid of fragmentation by combining adjacent blocks that are under half full. So, again, why bother doing an OPTIMIZE.

          • Your question asks about "fixed-length" fields -- that applies only to MyISAM, which has a radically different table structure.


          Does the DELETE take a long time? Is it a burden on the rest of the activity in the server? If so, there is a much better solution than OPTIMIZE... Partition.



          I would consider partitioning on 5-minute intervals. And do a DROP PARTITION every 5 minutes. It will be a lot less invasive than a big DELETE. More discussion: http://mysql.rjweb.org/doc.php/partitionmaint



          How often do you currently do the DELETE? Even if you don't go with PARTITIONing, write a script that continually repeats the DELETE. This will decrease the impact significantly over any approach using cron.



          Side issues:



          Indexing counter is quite a burden. Each time a counter is updated, the old index entry needs to be removed and an new entry needs to be added somewhere else.



          Why are deleting on date? You might be bumping the counter one second, then deleting the row the next second.






          share|improve this answer























            Your Answer








            StackExchange.ready(function() {
            var channelOptions = {
            tags: "".split(" "),
            id: "182"
            };
            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: false,
            noModals: true,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: null,
            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%2fdba.stackexchange.com%2fquestions%2f201794%2fshould-i-defragment-innodb-table-with-fixed-length-fields%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown

























            2 Answers
            2






            active

            oldest

            votes








            2 Answers
            2






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes









            0














            I would say yes for four(4) major reasons




            1. Page Boundaries / Index Pages

            2. Index Layout

            3. Index Statistics

            4. Bulk DML


            PAGE BOUNDARIES / INDEX PAGES



            According to the MySQL Documentation on Limits on InnoDB tables




            The maximum row length, except for variable-length columns (VARBINARY, VARCHAR, BLOB and TEXT), is slightly less than half of a page for 4KB, 8KB, 16KB, and 32KB page sizes. For example, the maximum row length for the default innodb_page_size of 16KB is about 8000 bytes. For an InnoDB page size of 64KB, the maximum row length is about 16000 bytes. LONGBLOB and LONGTEXT columns must be less than 4GB, and the total row length, including BLOB and TEXT columns, must be less than 4GB.




            Your table uses INT UNSIGNED (4 bytes), DATETIME (8 bytes), 2 SMALLINTs (4 bytes) per row. That's a total of 16 bytes per row. This means you can fit 1000 rows into a single InnoDB page, but there is a very small piece of fragmentation. Using the default innodb_page_size (16K or 16384), there will be 384 bytes of fragmentation with a page. It is most likely used for mapping the data within the one page.



            Doing mass INSERTs, DELETEs, and UPDATEs will generate many pages with empty space for whole rows that are marked as unused. This is in addition to the 384 bytes region of the data page.



            INDEX LAYOUT



            You will generate many index pages




            • You have a 6-byte PRIMARY KEY

            • Each secondary index carries a copy of the PRIMARY KEY


            • KEY external_id (external_id), will be 8 bytes (SMALLINT + PRIMARY KEY)


            • KEY counter (counter), will be 8 bytes (SMALLINT + PRIMARY KEY)


            • KEY date_idx (date) will be 14 bytes (DATE + PRIMARY KEY)

            • 36 bytes for indexing a single row

            • Indexes are represented as BTREEs, so you are looking at O(n log n) space utilization. If you account for non-leaf page splits, many index pages will be 50% empty (without question).


            INDEX STATISTICS



            Running INSERTs, DELETEs, and UPDATEs will skew index stats since index cardinalities will frequently change. You need to run ANALYZE TABLE tbl_log;. Running OPTIMIZE TABLE tbl_log; will defrag the tables and run ANALYZE TABLE tbl_log; as the last step (See my post from Feb 27, 2013 : What is the difference between optimize table and analyze table in mysql)



            BULK DML



            The DELETE query you will be doing by the hour is a bulk operation. Many rows will need a ton of housecleaning to keep up with marking rows deleted.






            share|improve this answer
























            • No, you can't hold 1000 rows per page. There is per-column, per-row, and per-block overheads. You'll be lucky to get 500 rows/block.

              – Rick James
              Mar 23 '18 at 0:55











            • DATETIME is no longer 8 bytes, but only 5 in newer versions.

              – Rick James
              Mar 23 '18 at 0:57











            • The PK is 9 bytes, not 6. Hence, all the math about secondary keys is off. Plus there is overhead in secondary key BTrees.

              – Rick James
              Mar 23 '18 at 0:57













            • Block splits lead to the BTree being an average of 69% full. This is not bad, and should be ignored.

              – Rick James
              Mar 23 '18 at 1:00
















            0














            I would say yes for four(4) major reasons




            1. Page Boundaries / Index Pages

            2. Index Layout

            3. Index Statistics

            4. Bulk DML


            PAGE BOUNDARIES / INDEX PAGES



            According to the MySQL Documentation on Limits on InnoDB tables




            The maximum row length, except for variable-length columns (VARBINARY, VARCHAR, BLOB and TEXT), is slightly less than half of a page for 4KB, 8KB, 16KB, and 32KB page sizes. For example, the maximum row length for the default innodb_page_size of 16KB is about 8000 bytes. For an InnoDB page size of 64KB, the maximum row length is about 16000 bytes. LONGBLOB and LONGTEXT columns must be less than 4GB, and the total row length, including BLOB and TEXT columns, must be less than 4GB.




            Your table uses INT UNSIGNED (4 bytes), DATETIME (8 bytes), 2 SMALLINTs (4 bytes) per row. That's a total of 16 bytes per row. This means you can fit 1000 rows into a single InnoDB page, but there is a very small piece of fragmentation. Using the default innodb_page_size (16K or 16384), there will be 384 bytes of fragmentation with a page. It is most likely used for mapping the data within the one page.



            Doing mass INSERTs, DELETEs, and UPDATEs will generate many pages with empty space for whole rows that are marked as unused. This is in addition to the 384 bytes region of the data page.



            INDEX LAYOUT



            You will generate many index pages




            • You have a 6-byte PRIMARY KEY

            • Each secondary index carries a copy of the PRIMARY KEY


            • KEY external_id (external_id), will be 8 bytes (SMALLINT + PRIMARY KEY)


            • KEY counter (counter), will be 8 bytes (SMALLINT + PRIMARY KEY)


            • KEY date_idx (date) will be 14 bytes (DATE + PRIMARY KEY)

            • 36 bytes for indexing a single row

            • Indexes are represented as BTREEs, so you are looking at O(n log n) space utilization. If you account for non-leaf page splits, many index pages will be 50% empty (without question).


            INDEX STATISTICS



            Running INSERTs, DELETEs, and UPDATEs will skew index stats since index cardinalities will frequently change. You need to run ANALYZE TABLE tbl_log;. Running OPTIMIZE TABLE tbl_log; will defrag the tables and run ANALYZE TABLE tbl_log; as the last step (See my post from Feb 27, 2013 : What is the difference between optimize table and analyze table in mysql)



            BULK DML



            The DELETE query you will be doing by the hour is a bulk operation. Many rows will need a ton of housecleaning to keep up with marking rows deleted.






            share|improve this answer
























            • No, you can't hold 1000 rows per page. There is per-column, per-row, and per-block overheads. You'll be lucky to get 500 rows/block.

              – Rick James
              Mar 23 '18 at 0:55











            • DATETIME is no longer 8 bytes, but only 5 in newer versions.

              – Rick James
              Mar 23 '18 at 0:57











            • The PK is 9 bytes, not 6. Hence, all the math about secondary keys is off. Plus there is overhead in secondary key BTrees.

              – Rick James
              Mar 23 '18 at 0:57













            • Block splits lead to the BTree being an average of 69% full. This is not bad, and should be ignored.

              – Rick James
              Mar 23 '18 at 1:00














            0












            0








            0







            I would say yes for four(4) major reasons




            1. Page Boundaries / Index Pages

            2. Index Layout

            3. Index Statistics

            4. Bulk DML


            PAGE BOUNDARIES / INDEX PAGES



            According to the MySQL Documentation on Limits on InnoDB tables




            The maximum row length, except for variable-length columns (VARBINARY, VARCHAR, BLOB and TEXT), is slightly less than half of a page for 4KB, 8KB, 16KB, and 32KB page sizes. For example, the maximum row length for the default innodb_page_size of 16KB is about 8000 bytes. For an InnoDB page size of 64KB, the maximum row length is about 16000 bytes. LONGBLOB and LONGTEXT columns must be less than 4GB, and the total row length, including BLOB and TEXT columns, must be less than 4GB.




            Your table uses INT UNSIGNED (4 bytes), DATETIME (8 bytes), 2 SMALLINTs (4 bytes) per row. That's a total of 16 bytes per row. This means you can fit 1000 rows into a single InnoDB page, but there is a very small piece of fragmentation. Using the default innodb_page_size (16K or 16384), there will be 384 bytes of fragmentation with a page. It is most likely used for mapping the data within the one page.



            Doing mass INSERTs, DELETEs, and UPDATEs will generate many pages with empty space for whole rows that are marked as unused. This is in addition to the 384 bytes region of the data page.



            INDEX LAYOUT



            You will generate many index pages




            • You have a 6-byte PRIMARY KEY

            • Each secondary index carries a copy of the PRIMARY KEY


            • KEY external_id (external_id), will be 8 bytes (SMALLINT + PRIMARY KEY)


            • KEY counter (counter), will be 8 bytes (SMALLINT + PRIMARY KEY)


            • KEY date_idx (date) will be 14 bytes (DATE + PRIMARY KEY)

            • 36 bytes for indexing a single row

            • Indexes are represented as BTREEs, so you are looking at O(n log n) space utilization. If you account for non-leaf page splits, many index pages will be 50% empty (without question).


            INDEX STATISTICS



            Running INSERTs, DELETEs, and UPDATEs will skew index stats since index cardinalities will frequently change. You need to run ANALYZE TABLE tbl_log;. Running OPTIMIZE TABLE tbl_log; will defrag the tables and run ANALYZE TABLE tbl_log; as the last step (See my post from Feb 27, 2013 : What is the difference between optimize table and analyze table in mysql)



            BULK DML



            The DELETE query you will be doing by the hour is a bulk operation. Many rows will need a ton of housecleaning to keep up with marking rows deleted.






            share|improve this answer













            I would say yes for four(4) major reasons




            1. Page Boundaries / Index Pages

            2. Index Layout

            3. Index Statistics

            4. Bulk DML


            PAGE BOUNDARIES / INDEX PAGES



            According to the MySQL Documentation on Limits on InnoDB tables




            The maximum row length, except for variable-length columns (VARBINARY, VARCHAR, BLOB and TEXT), is slightly less than half of a page for 4KB, 8KB, 16KB, and 32KB page sizes. For example, the maximum row length for the default innodb_page_size of 16KB is about 8000 bytes. For an InnoDB page size of 64KB, the maximum row length is about 16000 bytes. LONGBLOB and LONGTEXT columns must be less than 4GB, and the total row length, including BLOB and TEXT columns, must be less than 4GB.




            Your table uses INT UNSIGNED (4 bytes), DATETIME (8 bytes), 2 SMALLINTs (4 bytes) per row. That's a total of 16 bytes per row. This means you can fit 1000 rows into a single InnoDB page, but there is a very small piece of fragmentation. Using the default innodb_page_size (16K or 16384), there will be 384 bytes of fragmentation with a page. It is most likely used for mapping the data within the one page.



            Doing mass INSERTs, DELETEs, and UPDATEs will generate many pages with empty space for whole rows that are marked as unused. This is in addition to the 384 bytes region of the data page.



            INDEX LAYOUT



            You will generate many index pages




            • You have a 6-byte PRIMARY KEY

            • Each secondary index carries a copy of the PRIMARY KEY


            • KEY external_id (external_id), will be 8 bytes (SMALLINT + PRIMARY KEY)


            • KEY counter (counter), will be 8 bytes (SMALLINT + PRIMARY KEY)


            • KEY date_idx (date) will be 14 bytes (DATE + PRIMARY KEY)

            • 36 bytes for indexing a single row

            • Indexes are represented as BTREEs, so you are looking at O(n log n) space utilization. If you account for non-leaf page splits, many index pages will be 50% empty (without question).


            INDEX STATISTICS



            Running INSERTs, DELETEs, and UPDATEs will skew index stats since index cardinalities will frequently change. You need to run ANALYZE TABLE tbl_log;. Running OPTIMIZE TABLE tbl_log; will defrag the tables and run ANALYZE TABLE tbl_log; as the last step (See my post from Feb 27, 2013 : What is the difference between optimize table and analyze table in mysql)



            BULK DML



            The DELETE query you will be doing by the hour is a bulk operation. Many rows will need a ton of housecleaning to keep up with marking rows deleted.







            share|improve this answer












            share|improve this answer



            share|improve this answer










            answered Mar 20 '18 at 16:43









            RolandoMySQLDBARolandoMySQLDBA

            142k24223379




            142k24223379













            • No, you can't hold 1000 rows per page. There is per-column, per-row, and per-block overheads. You'll be lucky to get 500 rows/block.

              – Rick James
              Mar 23 '18 at 0:55











            • DATETIME is no longer 8 bytes, but only 5 in newer versions.

              – Rick James
              Mar 23 '18 at 0:57











            • The PK is 9 bytes, not 6. Hence, all the math about secondary keys is off. Plus there is overhead in secondary key BTrees.

              – Rick James
              Mar 23 '18 at 0:57













            • Block splits lead to the BTree being an average of 69% full. This is not bad, and should be ignored.

              – Rick James
              Mar 23 '18 at 1:00



















            • No, you can't hold 1000 rows per page. There is per-column, per-row, and per-block overheads. You'll be lucky to get 500 rows/block.

              – Rick James
              Mar 23 '18 at 0:55











            • DATETIME is no longer 8 bytes, but only 5 in newer versions.

              – Rick James
              Mar 23 '18 at 0:57











            • The PK is 9 bytes, not 6. Hence, all the math about secondary keys is off. Plus there is overhead in secondary key BTrees.

              – Rick James
              Mar 23 '18 at 0:57













            • Block splits lead to the BTree being an average of 69% full. This is not bad, and should be ignored.

              – Rick James
              Mar 23 '18 at 1:00

















            No, you can't hold 1000 rows per page. There is per-column, per-row, and per-block overheads. You'll be lucky to get 500 rows/block.

            – Rick James
            Mar 23 '18 at 0:55





            No, you can't hold 1000 rows per page. There is per-column, per-row, and per-block overheads. You'll be lucky to get 500 rows/block.

            – Rick James
            Mar 23 '18 at 0:55













            DATETIME is no longer 8 bytes, but only 5 in newer versions.

            – Rick James
            Mar 23 '18 at 0:57





            DATETIME is no longer 8 bytes, but only 5 in newer versions.

            – Rick James
            Mar 23 '18 at 0:57













            The PK is 9 bytes, not 6. Hence, all the math about secondary keys is off. Plus there is overhead in secondary key BTrees.

            – Rick James
            Mar 23 '18 at 0:57







            The PK is 9 bytes, not 6. Hence, all the math about secondary keys is off. Plus there is overhead in secondary key BTrees.

            – Rick James
            Mar 23 '18 at 0:57















            Block splits lead to the BTree being an average of 69% full. This is not bad, and should be ignored.

            – Rick James
            Mar 23 '18 at 1:00





            Block splits lead to the BTree being an average of 69% full. This is not bad, and should be ignored.

            – Rick James
            Mar 23 '18 at 1:00













            0














            I say "no" for various reasons.




            • The fragmentation will recur promptly after the OPTIMIZE, so why bother.

            • The fragmentation is not that big a deal. The performance issue is minimal. The "depth" of the BTrees rarely changes due to fragmentation.

            • InnoDB tends to get rid of fragmentation by combining adjacent blocks that are under half full. So, again, why bother doing an OPTIMIZE.

            • Your question asks about "fixed-length" fields -- that applies only to MyISAM, which has a radically different table structure.


            Does the DELETE take a long time? Is it a burden on the rest of the activity in the server? If so, there is a much better solution than OPTIMIZE... Partition.



            I would consider partitioning on 5-minute intervals. And do a DROP PARTITION every 5 minutes. It will be a lot less invasive than a big DELETE. More discussion: http://mysql.rjweb.org/doc.php/partitionmaint



            How often do you currently do the DELETE? Even if you don't go with PARTITIONing, write a script that continually repeats the DELETE. This will decrease the impact significantly over any approach using cron.



            Side issues:



            Indexing counter is quite a burden. Each time a counter is updated, the old index entry needs to be removed and an new entry needs to be added somewhere else.



            Why are deleting on date? You might be bumping the counter one second, then deleting the row the next second.






            share|improve this answer




























              0














              I say "no" for various reasons.




              • The fragmentation will recur promptly after the OPTIMIZE, so why bother.

              • The fragmentation is not that big a deal. The performance issue is minimal. The "depth" of the BTrees rarely changes due to fragmentation.

              • InnoDB tends to get rid of fragmentation by combining adjacent blocks that are under half full. So, again, why bother doing an OPTIMIZE.

              • Your question asks about "fixed-length" fields -- that applies only to MyISAM, which has a radically different table structure.


              Does the DELETE take a long time? Is it a burden on the rest of the activity in the server? If so, there is a much better solution than OPTIMIZE... Partition.



              I would consider partitioning on 5-minute intervals. And do a DROP PARTITION every 5 minutes. It will be a lot less invasive than a big DELETE. More discussion: http://mysql.rjweb.org/doc.php/partitionmaint



              How often do you currently do the DELETE? Even if you don't go with PARTITIONing, write a script that continually repeats the DELETE. This will decrease the impact significantly over any approach using cron.



              Side issues:



              Indexing counter is quite a burden. Each time a counter is updated, the old index entry needs to be removed and an new entry needs to be added somewhere else.



              Why are deleting on date? You might be bumping the counter one second, then deleting the row the next second.






              share|improve this answer


























                0












                0








                0







                I say "no" for various reasons.




                • The fragmentation will recur promptly after the OPTIMIZE, so why bother.

                • The fragmentation is not that big a deal. The performance issue is minimal. The "depth" of the BTrees rarely changes due to fragmentation.

                • InnoDB tends to get rid of fragmentation by combining adjacent blocks that are under half full. So, again, why bother doing an OPTIMIZE.

                • Your question asks about "fixed-length" fields -- that applies only to MyISAM, which has a radically different table structure.


                Does the DELETE take a long time? Is it a burden on the rest of the activity in the server? If so, there is a much better solution than OPTIMIZE... Partition.



                I would consider partitioning on 5-minute intervals. And do a DROP PARTITION every 5 minutes. It will be a lot less invasive than a big DELETE. More discussion: http://mysql.rjweb.org/doc.php/partitionmaint



                How often do you currently do the DELETE? Even if you don't go with PARTITIONing, write a script that continually repeats the DELETE. This will decrease the impact significantly over any approach using cron.



                Side issues:



                Indexing counter is quite a burden. Each time a counter is updated, the old index entry needs to be removed and an new entry needs to be added somewhere else.



                Why are deleting on date? You might be bumping the counter one second, then deleting the row the next second.






                share|improve this answer













                I say "no" for various reasons.




                • The fragmentation will recur promptly after the OPTIMIZE, so why bother.

                • The fragmentation is not that big a deal. The performance issue is minimal. The "depth" of the BTrees rarely changes due to fragmentation.

                • InnoDB tends to get rid of fragmentation by combining adjacent blocks that are under half full. So, again, why bother doing an OPTIMIZE.

                • Your question asks about "fixed-length" fields -- that applies only to MyISAM, which has a radically different table structure.


                Does the DELETE take a long time? Is it a burden on the rest of the activity in the server? If so, there is a much better solution than OPTIMIZE... Partition.



                I would consider partitioning on 5-minute intervals. And do a DROP PARTITION every 5 minutes. It will be a lot less invasive than a big DELETE. More discussion: http://mysql.rjweb.org/doc.php/partitionmaint



                How often do you currently do the DELETE? Even if you don't go with PARTITIONing, write a script that continually repeats the DELETE. This will decrease the impact significantly over any approach using cron.



                Side issues:



                Indexing counter is quite a burden. Each time a counter is updated, the old index entry needs to be removed and an new entry needs to be added somewhere else.



                Why are deleting on date? You might be bumping the counter one second, then deleting the row the next second.







                share|improve this answer












                share|improve this answer



                share|improve this answer










                answered Mar 23 '18 at 1:16









                Rick JamesRick James

                42.9k22259




                42.9k22259






























                    draft saved

                    draft discarded




















































                    Thanks for contributing an answer to Database Administrators Stack Exchange!


                    • 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%2fdba.stackexchange.com%2fquestions%2f201794%2fshould-i-defragment-innodb-table-with-fixed-length-fields%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

                    Szabolcs (Ungheria) Altri progetti | Menu di navigazione48°10′14.56″N 21°29′33.14″E /...

                    Discografia di Klaus Schulze Indice Album in studio | Album dal vivo | Singoli | Antologie | Colonne...

                    How to make inet_server_addr() return localhost in spite of ::1/128RETURN NEXT in Postgres FunctionConnect to...