我有一个在我的网站中使用非常频繁的 MySQL 表,该表中有超过 250K 条记录。它是使用以下 sql 语句创建的:
CREATE TABLE `user_favorstocks` (
`id` int(10) NOT NULL AUTO_INCREMENT,
`uid` int(10) unsigned NOT NULL COMMENT 'user id',
`stockid` varchar(15) NOT NULL COMMENT '.SZ, .SH',
`added_date` varchar(10) NOT NULL COMMENT '20160101',
`is_deleted` tinyint(2) NOT NULL DEFAULT '0' COMMENT '0, 1',
`db_insert_time` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
`db_update_time` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `index_uid_stockid` (`uid`,`stockid`)
);
在创建语句中,已经声明了一个多列唯一键,但我想添加一个索引来加速查询。因为经常有
insert into user_favorstocks (uid, stockid, added_date) values ...
执行速度很慢(30-60 毫秒,有时 100+ 毫秒)。 uid
、stockid
字段相关的表还有update
、select
操作,比如
update user_favorstocks set is_deleted=1 where uid=xxx and stockid=xxx
或
select stockid, added_date from user_favorstocks where uid=xxx and is_delete=0
我应该像我说的那样添加索引吗?还是 unique key
声明已经意味着创建索引,所以我不需要这样做?
MySQL版本:
5.1.73-日志
我的.cnf:
[client]
#socket=/tmp/mysql.sock
default-character-set=utf8
[mysql]
auto-rehash
default-character-set=utf8
[mysqld]
#socket=/tmp/mysql.sock
# following 2:
datadir=/home/data/mysql
socket=/var/lib/mysql/mysql.sock
#basedir=/home/mysql/mysql-5.5
#datadir=/home/mysql/mysql-5.5/data
user=mysql
#log-error=/home/mysql/mysql-5.5/logs/error.log
#pid-file=/home/mysql/mysql-5.5/data/mysql.pid
#default-storage-engine=MyISAM
# Disabling symbolic-links is recommended to prevent assorted security risks;
# to do so, uncomment this line:
symbolic-links=0
#default-character-set=utf8
collation-server = utf8_unicode_ci
init-connect='SET NAMES utf8'
character-set-server = utf8
#character-set-database=utf8
#set-variable=wait_timeout=31536000
#set-variable=interactive_timeout=31536000
skip-external-locking
key_buffer_size = 256M
max_allowed_packet = 1M
table_open_cache = 256
sort_buffer_size = 1M
read_buffer_size = 1M
read_rnd_buffer_size = 4M
myisam_sort_buffer_size = 64M
thread_cache_size = 8
query_cache_size= 16M
# Try number of CPU's*2 for thread_concurrency
thread_concurrency = 8
# new
# sort_buffer_size = 4M
# read_buffer_size = 4M
# join_buffer_size = 6M
# read_rnd_buffer_size = 4M
# myisam_sort_buffer_size = 64M
# thread_cache_size = 16
# query_cache_size= 16M
# concurrent_insert = 2
# tmp_table_size = 64M
#
# innodb_buffer_pool_size = 1G
# #innodb_data_file_path = ibdata1:100M:autoextend
# #innodb_data_home_dir = /var/lib/mysql/data
# innodb_file_per_table = 1
# # 会影响日志写入
# #innodb_flush_log_at_trx_commit = 2
# #innodb_flush_method = O_DIRECT
# innodb_io_capacity = 2000
# innodb_large_prefix = 1
# innodb_log_buffer_size = 4198608
# innodb_log_file_size = 256M
# innodb_log_files_in_group = 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!
#
#skip-networking
# Replication Master Server (default)
# binary logging is required for replication
log-bin=mysql-bin
# binary logging format - mixed recommended
binlog_format=mixed
expire_logs_days = 90
# 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
[myisamchk]
key_buffer_size = 128M
sort_buffer_size = 128M
read_buffer = 2M
write_buffer = 2M
[mysqlhotcopy]
interactive-timeout
[mysqldump]
quick
max_allowed_packet = 16M
# following section:
[mysqld_safe]
log-error=/var/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid
我们目前在 16GB 服务器和 4 个 cpu 内核上运行此服务,并使用 InnoDB。
最佳答案
是的,唯一键已经是一个索引。您不需要再创建一个。额外的索引实际上会减慢插入语句的速度。但我不建议删除这个索引。您显然需要它用于更新和选择语句。
当您的插入语句很慢时,您可能可以通过调整服务器的其他方面来获得更好的性能,例如缓冲池的大小。发布您服务器的确切版本(SELECT version();
的结果)和您的 my.cnf(如果您使用的是 Windows,则为 my.ini)的内容。
关于mysql - 如果我已经在 MySQL 中声明了多列唯一键,还需要添加多列索引吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47451502/