On Wed, 03 May 2006 Rhino wrote :
Daniel de Veiga has already answered you on how to determine the size of your
database by using the file system and simply looking at the size of the
physical files in your database.
Another possibility is that you could use the SHOW TABLE STATUS command in
MySQL. If you go to your MySQL prompt and select a database, then use the SHOW
TABLE STATUS command, like this:
set tmp;
show table status like '%';
you'll find a column called Data_length which tells you "the length of the data
file" for each table. If you simply add the size of each table in the database
together, you should have the size of the whole database.
Please note that I'm not sure how accurate my suggestion is; you might find
that Daniel's approach gives you a better answer. I'm not sure if the
Data_length column considers all the overhead that you might have with a table,
such as index sizes, pointer sizes, unusable space, etc. Perhaps someone else
can jump in with a better approach; I'm inclined to think it can't be quite as
easy as I suggested.
I'll jump in for you..
Indeed, you are right that Data_length that does not cover space
allocated but unused (i.e space freed up by DELETE or UPDATE statements
that is not released back to the filesystem, before an OPTIMIZE TABLE
for example). There are other columns within the output however -
Data_free and Index_length.
Therefore to get the total allocated space to a database:
SUM(data_length) + SUM(index_length)
Total of actual data:
(SUM(data_length) - SUM(data_free)) + SUM(index_length)
Allocated but unused:
SUM(data_free)
Also, even if the Data_length column gives an accurate answer for the size of a
table, it is rather tedious to have to execute the SHOW TABLE STATUS command
and then manually sum up the various sizes. I don't think you can simply
execute an SQL query that does all the work for you, which is very unfortunate.
Unfortunately within 4.0 there is no way to do this with a SQL query.
You can do this on 5.0 however. For example:
SELECT s.schema_name,
CONCAT(IFNULL(ROUND((SUM(t.data_length)+SUM(t.index_length))
/1024/1024,2),0.00),"Mb") total_size,
CONCAT(IFNULL(ROUND(((SUM(t.data_length)+SUM(t.index_length))-SUM(t.data_free))/1024/1024,2),0.00),"Mb")
data_used,
CONCAT(IFNULL(ROUND(SUM(data_free)/1024/1024,2),0.00),"Mb") data_free,
IFNULL(ROUND((((SUM(t.data_length)+SUM(t.index_length))-SUM(t.data_free))
/((SUM(t.data_length)+SUM(t.index_length)))*100),2),0) pct_used,
COUNT(table_name) total_tables
FROM INFORMATION_SCHEMA.SCHEMATA s
LEFT JOIN INFORMATION_SCHEMA.TABLES t ON s.schema_name = t.table_schema
WHERE s.schema_name = "sakila"
GROUP BY s.schema_name
ORDER BY pct_used DESC\G
*************************** 1. row ***************************
schema_name: sakila
total_size: 6.62Mb
data_used: 6.62Mb
data_free: 0.01Mb
pct_used: 99.91
total_tables: 22
1 row in set (0.08 sec)
It is entirely possible that there is a MySQL command that gives you the actual
size of each database directly, although I didn't find it when I searched the
manual. Again, perhaps someone with more administrative experience with MySQL
can suggest a better approach. If not, perhaps we need to make a feature
request of the MySQL people :-) This would appear to be a very useful command
to create if it doesn't already exist!
I have a little administrative experience ;)
I'm going to confuse the matter now, as the above reports freespace
correctly for storage engines such as MyISAM, however, it does not
report the freespace properly within Data_free column for InnoDB tables
- the freespace is reported at the *tablespace* level, within the
"Comment" column of SHOW TABLE STATUS and INFORMATION_SCHEMA.TABLES.
There are a couple of other relatively undocumented features within
InnoDB that allow you to dump this kind of information - called the
"InnoDB Monitors":
http://dev.mysql.com/doc/refman/5.0/en/innodb-monitor.html
If you create the following table for a short period of time, the
internal contents of the InnoDB data dictionary will be dumped out to
the error log:
create table innodb_table_monitor (a int) engine = innodb;
Then drop the table after a minute or so (otherwise it will dump
continuously). This will dump a wealth of information on all of the
tables within InnoDB (for all databases), here's an extract on one of
our sakila tables:
TABLE: name sakila/rental, id 0 26, columns 11, indexes 5, appr.rows 16305
COLUMNS: rental_id: DATA_INT len 4 prec 0; rental_date: DATA_INT len 8
prec 0; inventory_id: DATA_INT len 3 prec 0; customer_id: DATA_INT len 2
prec 0; return_date: DATA_INT len 8 prec 0; staff_id: DATA_INT len 1
prec 0; last_update: DATA_INT len 4 prec 0; DB_ROW_ID: DATA_SYS prtype 8
len 6 prec 0; DB_TRX_ID: DATA_SYS prtype 8 len 6 prec 0; DB_ROLL_PTR:
DATA_SYS prtype 8 len 7 prec 0;
INDEX: name PRIMARY, id 0 44, fields 1/9, type 3
root page 207, appr.key vals 16305, leaf pages 53, size pages 97
FIELDS: rental_id DB_TRX_ID DB_ROLL_PTR rental_date inventory_id
customer_id return_date staff_id last_update
INDEX: name rental_date, id 0 45, fields 3/4, type 2
root page 208, appr.key vals 17655, leaf pages 28, size pages 29
FIELDS: rental_date inventory_id customer_id rental_id
INDEX: name idx_fk_inventory_id, id 0 46, fields 1/2, type 0
root page 210, appr.key vals 4467, leaf pages 16, size pages 17
FIELDS: inventory_id rental_id
INDEX: name idx_fk_customer_id, id 0 47, fields 1/2, type 0
root page 211, appr.key vals 589, leaf pages 16, size pages 17
FIELDS: customer_id rental_id
INDEX: name idx_fk_staff_id, id 0 48, fields 1/2, type 0
root page 212, appr.key vals 1, leaf pages 13, size pages 14
FIELDS: staff_id rental_id
FOREIGN KEY CONSTRAINT sakila/fk_rental_staff: sakila/rental ( staff_id )
REFERENCES sakila/staff ( staff_id )
FOREIGN KEY CONSTRAINT sakila/fk_rental_inventory: sakila/rental (
inventory_id )
REFERENCES sakila/inventory ( inventory_id )
FOREIGN KEY CONSTRAINT sakila/fk_rental_customer: sakila/rental (
customer_id )
REFERENCES sakila/customer ( customer_id )
FOREIGN KEY CONSTRAINT sakila/fk_payment_rental: sakila/payment (
rental_id )
REFERENCES sakila/rental ( rental_id )
As you can see - bunches of information (including showing the internal
columns used for transactions). However the things to note here are the
"leaf pages" and "size pages" for each index. "leaf pages" is the number
of pages that actually contain data (as indexes store their data in the
leaf nodes), whilst "size pages" is the total number of pages that are
allocated to the table.
InnoDB uses "clustered indexes" - so the data for each row is actually
stored within the PRIMARY KEY index for each table. Each "page" within
InnoDB is 16kb in size. So as you can see above for "Index: name
PRIMARY" we have "size_pages 97" (16,384 * 97 = 1,589,248 (1.5Mb))
allocated to the table within the InnoDB tablespace, with only "leaf
pages 53" (16,384 * (97-53) = 720,896 (~700Kb)) actually being used.
You can then perform the same kind of sum across the rest of the indexes
within each table to get an approximation such as that given for
Index_length within SHOW TABLE STATUS / INFORMATION_SCHEMA.TABLES as well.
Of course, this is not an easy method to use, there is no simple command
to quickly analyze this data (yet), it's mostly a manual process reading
through the dump file - however shouldn't be that hard to script, either.
Hope this helps!
Best regards
Mark
--
Mark Leith, Support Engineer
MySQL AB, Worcester, England, www.mysql.com
Are you MySQL certified? www.mysql.com/certification
--
MySQL General Mailing List
For list archives: http://lists.mysql.com/mysql
To unsubscribe: http://lists.mysql.com/[EMAIL PROTECTED]