mysql - 如果我已经在 MySQL 中声明了多列唯一键,还需要添加多列索引吗?

标签 mysql

我有一个在我的网站中使用非常频繁的 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+ 毫秒)。 uidstockid字段相关的表还有updateselect操作,比如

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/

相关文章:

php - 获取某个主题中的帖子数量 PHP

mysql - C# mysql 75英里半径 map 覆盖整个美国

php - 如何在 MySQL 中生成唯一的字母数字内容?

php - 购物车功能、更新和清除字段

php - 添加数据时的SQLSTATE [42000]

php - 相当于 mysql 和 eloquent 查询生成器

union/join 联合使用的mysql问题

mysql - 如何在SQL查询中根据某些条件执行减法?

php - 是否可以自行连接单个表?

php - 如何在 MAMP Pro 上升级 phpMyAdmin?