i'm currently trying to optimize my database. The problem is the following:
I have a table which currently stores over 83Mio. timedependent values. They are indexed by a highres (ms) timestamp. What i need to do is count how many times a certain value appears in a given interval of time - for example say i want to know how many times value 1.56787 appeared in the interval form timestamp x to timestamp y. Right now this takes almost forever.
Im using InnoDB and i already put a lot of time into optimizing the config files, which increased the speed immensly.
Im thankful for any input, as im pretty much running out of ideas how to pull this off. The only workaround i can think of is to create tables which contain pre counted values for fixed intervals, which would not be really satisfying since the whole thing should also be fully updateable (we are talking about new values arriving every few milliseconds). Would another db system be better suited for my problem?
Here is the explain output:
Field Type Null Key Default Extra
timestamp bigint(20) NO PRI NULL
ask decimal(6,5) NO NULL
bid decimal(6,5) NO NULL
askvolume decimal(6,5) NO NULL
bidvolume decimal(6,5) NO NULL
# The MySQL server
[mysqld]
port= 3306
socket= "C:/xampp/mysql/mysql.sock"
basedir="C:/xampp/mysql"
tmpdir="C:/xampp/tmp"
datadir="C:/xampp/mysql/data"
pid_file="mysql.pid"
skip-external-locking
key_buffer = 16M
max_allowed_packet = 61M
table_cache = 64
sort_buffer_size = 512K
net_buffer_length = 8K
read_buffer_size = 256K
read_rnd_buffer_size = 512K
myisam_sort_buffer_size = 8M
log_error="mysql_error.log"
bind-address="192.168.1.2"
# Don't listen on a TCP/IP port at all. This can be a security enhancement,
# if all processes that need to connect to mysqld run on the same host.
# All interaction with mysqld must be made via Unix sockets or named pipes.
# Note that using this option without enabling named pipes on Windows
# (via the "enable-named-pipe" option) will render mysqld useless!
#
# commented in by lampp security
#skip-networking
skip-federated
# Replication Master Server (default)
# binary logging is required for replication
# log-bin deactivated by default since XAMPP 1.4.11
#log-bin=mysql-bin
# required unique id between 1 and 2^32 - 1
# defaults to 1 if master-host is not set
# but will not function as a master if omitted
server-id = 1
# Replication Slave (comment out master section to use this)
#
# To configure this host as a replication slave, you can choose between
# two methods :
#
# 1) Use the CHANGE MASTER TO command (fully described in our manual) -
# the syntax is:
#
# CHANGE MASTER TO MASTER_HOST=<host>, MASTER_PORT=<port>,
# MASTER_USER=<user>, MASTER_PASSWORD=<password> ;
#
# where you replace <host>, <user>, <password> by quoted strings and
# <port> by the master's port number (3306 by default).
#
# Example:
#
# CHANGE MASTER TO MASTER_HOST='125.564.12.1', MASTER_PORT=3306,
# MASTER_USER='joe', MASTER_PASSWORD='secret';
#
# OR
#
# 2) Set the variables below. However, in case you choose this method, then
# start replication for the first time (even unsuccessfully, for example
# if you mistyped the password in master-password and the slave fails to
# connect), the slave will create a master.info file, and any later
# change in this file to the variables' values below will be ignored and
# overridden by the content of the master.info file, unless you shutdown
# the slave server, delete master.info and restart the slaver server.
# For that reason, you may want to leave the lines below untouched
# (commented) and instead use CHANGE MASTER TO (see above)
#
# required unique id between 2 and 2^32 - 1
# (and different from the master)
# defaults to 2 if master-host is set
# but will not function as a slave if omitted
#server-id = 2
#
# The replication master for this slave - required
#master-host = <hostname>
#
# The username the slave will use for authentication when connecting
# to the master - required
#master-user = <username>
#
# The password the slave will authenticate with when connecting to
# the master - required
#master-password = <password>
#
# The port the master is listening on.
# optional - defaults to 3306
#master-port = <port>
#
# binary logging - not required for slaves, but recommended
#log-bin=mysql-bin
# Point the following paths to different dedicated disks
#tmpdir = "C:/xampp/tmp"
#log-update = /path-to-dedicated-directory/hostname
# Uncomment the following if you are using BDB tables
#bdb_cache_size = 4M
#bdb_max_lock = 10000
# Comment the following if you are using InnoDB tables
#skip-innodb
innodb_data_home_dir = "C:/xampp/mysql/data"
innodb_data_file_path = ibdata1:10M:autoextend
innodb_log_group_home_dir = "C:/xampp/mysql/data"
#innodb_log_arch_dir = "C:/xampp/mysql/data"
## You can set .._buffer_pool_size up to 50 - 80 %
## of RAM but beware of setting memory usage too high
innodb_buffer_pool_size = 1024M
innodb_additional_mem_pool_size = 20M
## Set .._log_file_size to 25 % of buffer pool size
innodb_log_file_size = 5M
innodb_log_buffer_size = 16M
innodb_flush_log_at_trx_commit = 0
innodb_lock_wait_timeout = 50
[mysqldump]
quick
max_allowed_packet = 16M
[mysql]
no-auto-rehash
# Remove the next comment character if you are not familiar with SQL
#safe-updates
[isamchk]
key_buffer = 20M
sort_buffer_size = 20M
read_buffer = 2M
write_buffer = 2M
[myisamchk]
key_buffer = 20M
sort_buffer_size = 20M
read_buffer = 2M
write_buffer = 2M
[mysqlhotcopy]
interactive-timeout
Oh the machine is an i7-950 with 6GB of RAM and the system+database is on a SSD. So i think that should not be the problem?
Thanks for your help, it will be highly appreciated!
I don't have a feel for the range of values that you have in you indexed timestamp value but it seems to me that partitioning your table could help you out here. Specifically RANGE partitioning or HASH partitioning.
This should give you a significant performance boost.
If the time ranges can be expressed as a series of ranges (months, days, weeks, etc.), you might introduce something like a date-prefix column, that will significatly reduce the number of examined rows using IN() expression.
Here is an article that exposes the idea: http://www.mysqlperformanceblog.com/2010/01/09/getting-around-optimizer-limitations-with-an-in-list/
First step: if you haven't done it, use explain plan to see what exactly is the bottleneck of your query, and if the engine is using the index(es) correctly.
Second step: partition your table by range on the timestamp. I'm not sure if MySQL/InnoDB has that capability, but if it doesn't you'd better change DBMS.
In any case, MySQL is not really a good choice for high performance: depending on your needs you may be better off with Oracle or Postgre, or even an in-memory storage (especially if you don't care too much for safety as opposed to performance).
Related
Hello dear StackOverflow community,
I have a large WordPress site that now crashes the database by creating dozens of Creating sort index tasks with:
SELECT t.*, tt.*
FROM wp_terms AS t
INNER JOIN wp_term_taxonomy AS tt ON t.term_id = tt.term_id
WHERE tt.taxonomy IN ('categories')
ORDER BY t.name ASC
Those run for more than 20 seconds +. Afterwards its "sending data" with the same SQL query. The server is using an AMD epyc cpu and shouldn't have any problems (even though the database is large) and it did not have until it suddenly seems to be stuck.
Shouldn't it be caching this query anyways?
The mariadb my.cf config looks like:
#
# These groups are read by MariaDB server.
# Use it for options that only the server (but not clients) should see
# this is read by the standalone daemon and embedded servers
[server]
# this is only for the mysqld standalone daemon
[mysqld]
#
# * Basic Settings
#
user = mysql
pid-file = /run/mysqld/mysqld.pid
basedir = /usr
datadir = /var/lib/mysql
tmpdir = /tmp
lc-messages-dir = /usr/share/mysql
lc-messages = en_US
skip-external-locking
# Broken reverse DNS slows down connections considerably and name resolve is
# safe to skip if there are no "host by domain name" access grants
#skip-name-resolve
# Instead of skip-networking the default is now to listen only on
# localhost which is more compatible and is not less secure.
bind-address = 127.0.0.1
#
# * Fine Tuning
#
#key_buffer_size = 128M
#max_allowed_packet = 1G
#thread_stack = 192K
#thread_cache_size = 8
# This replaces the startup script and checks MyISAM tables if needed
# the first time they are touched
#myisam_recover_options = BACKUP
#max_connections = 100
#table_cache = 64
#
# * Logging and Replication
#
# Both location gets rotated by the cronjob.
# Be aware that this log type is a performance killer.
# Recommend only changing this at runtime for short testing periods if needed!
#general_log_file = /var/log/mysql/mysql.log
#general_log = 1
# When running under systemd, error logging goes via stdout/stderr to journald
# and when running legacy init error logging goes to syslog due to
# /etc/mysql/conf.d/mariadb.conf.d/50-mysqld_safe.cnf
# Enable this if you want to have error logging into a separate file
#log_error = /var/log/mysql/error.log
# Enable the slow query log to see queries with especially long duration
#slow_query_log_file = /var/log/mysql/mariadb-slow.log
#long_query_time = 10
#log_slow_verbosity = query_plan,explain
#log-queries-not-using-indexes
#min_examined_row_limit = 1000
# The following can be used as easy to replay backup logs or for replication.
# note: if you are setting up a replication slave, see README.Debian about
# other settings you may need to change.
#server-id = 1
#log_bin = /var/log/mysql/mysql-bin.log
expire_logs_days = 10
#max_binlog_size = 100M
# * Character sets
#
# MySQL/MariaDB default is Latin1, but in Debian we rather default to the full
# utf8 4-byte character set. See also client.cnf
character-set-server = utf8mb4
collation-server = utf8mb4_general_ci
#
# * InnoDB
#
# InnoDB is enabled by default with a 10MB datafile in /var/lib/mysql/.
# Read the manual for more InnoDB related options. There are many!
# Most important is to give InnoDB 80 % of the system RAM for buffer use:
# https://mariadb.com/kb/en/innodb-system-variables/#innodb_buffer_pool_size
#innodb_buffer_pool_size = 8G
# this is only for embedded server
[embedded]
# This group is only read by MariaDB servers, not by MySQL.
# If you use the same .cnf file for MySQL and MariaDB,
# you can put MariaDB-only options here
[mariadb]
# This group is only read by MariaDB-10.5 servers.
# If you use the same .cnf file for MariaDB of different versions,
# use this group for options that older servers don't understand
[mariadb-10.5]
I restarted mariadb, but the advisor mentions a huge rate of opening tables (same for files). The server is running only for 15 minutes. Is this due to the short time or do I have to change the settings (before the huge amount of Creating sort index tasks, the server was stable)
Issue:
The rate of opening tables is high.
Recommendation:
Opening tables requires disk I/O which is costly. Increasing table_open_cache might avoid this.
Justification:
Opened table rate: 1.26 per second, this value should be less than 10 per hour
Used variable / formula:
Opened_tables / Uptime
Test:
value*60*60 > 10
I would be awesome if somebody has an idea, what to do about that problem
I am trying to import a old Vbulletin database but always getting this error
ERROR 1114 (HY000) at line 4734: The table 'session' is full
this database backup size is 2GB and my server have 8GB ram. I tried to add innodb_data_file_path=ibdata1:10M:autoextend and innodb_file_per_table to my.cnf but not solved my problem.
my complete my.cnf
#
# The MySQL database server configuration file.
#
# You can copy this to one of:
# - "/etc/mysql/my.cnf" to set global options,
# - "~/.my.cnf" to set user-specific options.
#
# One can use all long options that the program supports.
# Run program with --help to get a list of available options and with
# --print-defaults to see which it would actually understand and use.
#
# For explanations see
# http://dev.mysql.com/doc/mysql/en/server-system-variables.html
# This will be passed to all mysql clients
# It has been reported that passwords should be enclosed with ticks/quotes
# escpecially if they contain "#" chars...
# Remember to edit /etc/mysql/debian.cnf when changing the socket location.
[client]
port = 3306
socket = /var/run/mysqld/mysqld.sock
[mysqld_safe]
socket = /var/run/mysqld/mysqld.sock
nice = 0
[mysqld]
user = mysql
pid-file = /var/run/mysqld/mysqld.pid
socket = /var/run/mysqld/mysqld.sock
port = 3306
basedir = /usr
datadir = /var/lib/mysql
tmpdir = /tmp
lc-messages-dir = /usr/share/mysql
skip-external-locking
bind-address = 127.0.0.1
key_buffer = 16M
max_allowed_packet = 16M
thread_stack = 192K
thread_cache_size = 8
myisam-recover = BACKUP
#max_connections = 100
#table_cache = 64
#thread_concurrency = 10
query_cache_limit = 1M
query_cache_size = 16M
expire_logs_days = 10
max_binlog_size = 100M
innodb_data_file_path=ibdata1:10M:autoextend
innodb_file_per_table
[mysqldump]
quick
quote-names
max_allowed_packet = 16M
[mysql]
[isamchk]
key_buffer = 16M
!includedir /etc/mysql/conf.d/
I am very familiar with Vbulletin database schema and tables. I have converted dozens of VB sites to Innodb storage engine.
The reason that you are getting that error is because the session table is a Memory table. The session table(s) must have been quite full when you took this backup that you are trying to restore. That, coupled with your overhead IO during the import, is filling up your RAM. However, for VB to work properly, you do not actually need this table to be a Memory table.
In order to get around this you can convert your session table to InnoDB.
I would open the .sql file up in a text editor (if possible) and change where it says ENGINE = MEMORY for your session table to InnoDB, or use string replace:
sed -i 's/MEMORY/INNODB/g' yourfilename.sql
I spent the last days studying alternatives to update my database , I have studied databases as MemSQL , VoltDB , and many other databases. I have a specific problem , in which case I have real-time data updates , and need to show this data quickly to my user. However I can not migrate to NoSQL solutions for the needs of Joins , ACID , Group By , among others.
I'm currently using the following structure:
1 Server 64 GB Ram 1600 Mhz / Xeon E5 3.7 Ghz / 160 GB SSD
MySQL InnoDB engine to save the data and not lose them and MySQL Memory Engine to perform the Selects in real time updated via Trigger.
This structure is good , but do not increase much my performace and my amount of records is increasing too .
From that, I started to test other database, looking for a solution that could scale and found MySQL Cluster . I have tested MySQL Cluster the last days and the performace it is far below the MySQL Memory Engine, comparative 4-5x slower for some queries .
Have my infrastructure for MySQL Cluster are 4 machines with the same configuration above , one NDB Manager , MySQL SQL Node 1 , Node 2 Date ( 1 Node Group with replication) . In this case I have a super hardware, because as I said , I have a major concern with real time.
A case I'm testing is as follows , I have a table with 5 million records , with one column I need to perform a " ( count (distinct (column ) ) " are using Index BTREE . My query is basically the following
MySQL Memory Engine :
select sql_no_cache COUNT(DISTINCT(id)) from my_data;
/* Affected rows: 0 Registros encontrados: 1 Avisos: 0 Duração de 1 query: 0,109 sec. */
MySQL Cluster :
select sql_no_cache COUNT(DISTINCT(id)) from my_data;
/* Affected rows: 0 Registros encontrados: 1 Avisos: 0 Duração de 1 query: 0,485 sec. */
For MySQL Memory Engine, i have a my.cnf boosted , some values are bigger than I need , but it is working as well , see below:
[mysqld]
socket = /var/run/mysqld/mysqld.sock
basedir = /usr
datadir = /var/lib/mysql
tmpdir = /tmp
lc-messages-dir = /usr/share/mysql
skip-external-locking
# * Fine Tuning
key_buffer = 16G
max_allowed_packet = 4G
table_open_cache = 16384
sort_buffer_size = 8G
read_buffer_size = 8G
read_rnd_buffer_size = 16G
myisam_sort_buffer_size = 16G
thread_cache_size = 256
thread_concurrency = 128
thread_stack = 8192K
myisam-recover = BACKUP
max_connections = 5000
# * Query Cache Configuration
query_cache_limit = 2G
query_cache_size = 8G
tmp_table_size = 16G
max_heap_table_size = 32G
# * Logging and Replication
general_log_file = /var/log/mysql/mysql.log
general_log = 1
log_error = /var/log/mysql/error.log
log_slow_queries = /var/log/mysql/mysql-slow.log
long_query_time = 1
log-queries-not-using-indexes
log_bin = /var/log/mysql/mysql-bin.log
expire_logs_days = 10
max_binlog_size = 100M
# INNODB
innodb_buffer_pool_size = 48G
innodb_additional_mem_pool_size = 32G
innodb_file_per_table = 1
innodb_file_format = barracuda
[mysqldump]
quick
quote-names
max_allowed_packet = 8G
[mysql]
#no-auto-rehash # faster start of mysql but no tab completition
[isamchk]
key_buffer = 16G
[myisamchk]
key_buffer_size = 24G
sort_buffer_size = 24G
read_buffer = 16G
write_buffer = 16G
As for MySQL Cluster , the Config.ini file is as follows:
[ndbd default]
# Options affecting ndbd processes on all data nodes:
NoOfReplicas=2 # Number of replicas
DataMemory=32G # How much memory to allocate for data storage
IndexMemory=16G # How much memory to allocate for index storage
# For DataMemory and IndexMemory, we have used the
# default values. Since the "world" database takes up
# only about 500KB, this should be more than enough for
# this example Cluster setup.
MaxNoOfTables=4096
MaxNoOfTriggers=3500
MaxNoOfAttributes=10000
MaxNoOfOrderedIndexes=1000
MaxNoOfUniqueHashIndexes=1000
MaxNoOfConcurrentIndexOperations=32K
MaxNoOfConcurrentOperations=128K
SharedGlobalMemory=1G
DiskPageBufferMemory=1G
[ndb_mgmd]
NodeId=20
# Management process options:
hostname=192.168.0.1 # Hostname or IP address of MGM node
datadir=/var/lib/mysql-cluster # Directory for MGM node log files
[ndbd]
#Data Node 1
NodeId=1
NodeGroup=0
hostname=192.168.0.2 # Hostname or IP address
datadir=/usr/local/mysql/data # Directory for this data nodes data files
[ndbd]
#Data Node 2
NodeId=2
NodeGroup=0
hostname=192.168.0.3 # Hostname or IP address
datadir=/usr/local/mysql/data # Directory for this data nodes data files
[mysqld]
# SQL Node 1
NodeID=11
hostname=192.168.0.4 # Hostname or IP address
So what's wrong for MySQL Cluster not have the same performace MySQL Memory Engine?
I have a table which has 38.406.168 rows and according to size in phpmyadmin 4.5GB. I want to see the last row of the table. Unfortunately I couldn't use select * from ... limit 38.406.166,1 or even I couldn't use select count(*) from ... function.
I changed my.ini in wamp server, but still I get mysql server has gone away error while attempting execute one of these queries. BTW; I couldn't even set an index on ID to make these processes much quicker.
My last try was to export the table to look at the last row. However, It just shows me 123MB of the file.
What should I do? Please help me. The features of the computer is 2.93 GHz, 3.50GB
Here is my my.ini file:
# The MySQL server
[wampmysqld]
port = 3306
socket = /tmp/mysql.sock
skip-locking
key_buffer = 384M
max_allowed_packet = 2000M
table_cache = 4096
sort_buffer_size = 2000M
net_buffer_length = 8K
read_buffer_size = 2000M
read_rnd_buffer_size = 2000M
myisam_sort_buffer_size = 2000M
basedir=c:/wamp/bin/mysql/mysql5.1.36
log-error=c:/wamp/logs/mysql.log
datadir=c:/wamp/bin/mysql/mysql5.1.36/data
(.. these parts are deleted, since there is nothing to set as value)
# Uncomment the following if you are using InnoDB tables
#innodb_data_home_dir = C:\mysql\data/
#innodb_data_file_path = ibdata1:10M:autoextend
#innodb_log_group_home_dir = C:\mysql\data/
#innodb_log_arch_dir = C:\mysql\data/
# You can set .._buffer_pool_size up to 50 - 80 %
# of RAM but beware of setting memory usage too high
#innodb_buffer_pool_size = 384M
#innodb_additional_mem_pool_size = 20M
# Set .._log_file_size to 25 % of buffer pool size
#innodb_log_file_size = 10M
#innodb_log_buffer_size = 64M
#innodb_flush_log_at_trx_commit = 1
#innodb_lock_wait_timeout = 180
[mysqldump]
quick
max_allowed_packet = 160M
Thank you so much for your help
I tried a lot of stuff and ended up with those 2 working:
Simply mirror the database via mysql's internal master-slave-functions (try google, you ll find good tutorials) onto a simple backup server (most cheap hosting packages will work if they have ssh access)
Try http://www.mysqldumper.net/, the best tool to copy & split huge databases into 100mb-parts. This simple open source tool did everything that "professional" backup scripts couldn't do.
You will want to use the mysqldump command to do this. Here is what I do in linux, but I think it will translate to Windows (I see that you're running WAMP).
mysqldump --opt --force -Q --user=[your_user] -p [database_name] > dump.sql
You may need to change directory to where the mysqldump file is located:
cd c:\path\to\mysql\bin
I was wondering if these my.cnf values would be ok for a Xeon 2.33GHz VPS with 1GB of RAM.
There are ~5 sites on the server with low traffic and the server is running Apache/PHP/MySQL... Also I want to enable the MySQL query cache and would appreciate any advise re the amount of RAM to allocate to the cache...
MySQL Settings:
[mysqld]
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
user=mysql
# Default to using old password format for compatibility with mysql 3.x
# clients (those using the mysqlclient10 compatibility package).
old_passwords=1
# Disabling symbolic-links is recommended to prevent assorted security risks;
# to do so, uncomment this line:
# symbolic-links=0
key_buffer = 16K
max_allowed_packet = 1M
thread_stack = 64K
table_cache = 4
sort_buffer = 64K
net_buffer_length = 2K
bind-address = 127.0.0.1
[mysqld_safe]
log-error=/var/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid
Thanks for the help :)
Some memory chache was set too small compare to 1GB RAM, even if you may use a virtual machine actually.
Performance may be better if you change some options and that won't eat too much resources.
If you are not sue what to change, take a look at MySQL recommanded configuration.
These files was located at /usr/share/doc/mysql-server-x.x/examples
Your configuration may belongs to my-small.conf, my-medium.cnf is better suitable for you.
I recommend you use mytop to analyze real-time activity of your database.
Also used mysqltuner to give you suggestions on your my.cnf values.
Too enables logging of slow queries:
log_slow_queries = /var/log/mysql/mysql-slow.log
long_query_time = 3
The configuration of my dedicated server for a high rate of transactions if anything helps:
max_allowed_packet=16M
key_buffer_size=8M
innodb_additional_mem_pool_size=10M
innodb_buffer_pool_size=512M
join_buffer_size=40M
table_open_cache=1024
query_cache_size=40M
table_definition_cache=256
innodb_additional_mem_pool_size=10M
key_buffer_size=16M
max_allowed_packet=32M
max_connections = 300
query_cache_limit = 10M
log_slow_queries = /var/log/mysql/mysql-slow.log
long_query_time = 3
I hope it helps somewhat. If you want to refer details about these(and many other) server parameters, refer this Official MySQL Documentation
Regards.