MySQL 查询缓慢

标签 mysql performance

我有一个运行非常缓慢的查询。

运行大约需要 7 秒。

但是,如果我从查询中删除“and timestamp > 20130201”,它只需要不到 400 毫秒即可运行。

我想也许时间戳字段没有被索引,但它是,所以我想知道为什么将这样的日期添加到查询中会导致它变慢?

如果可以的话,我宁愿不删除那部分查询,但我不明白为什么它在那里会慢得多。

查询:

select p1_score,p2_score,p3_score,p4_score from game where  (p1_user_id='$uid' or p2_user_id='$uid' or p3_user_id='$uid' or p4_user_id='$uid') and turn=0 and timestamp > 20130201

解释:

1   SIMPLE  game    range   p1_user_id,p2_user_id,p3_user_id,p4_user_id,turn,timestamp  timestamp   4   NULL    51486   Using where

创建 SQL:

CREATE TABLE `game` (
  `id` bigint(10) NOT NULL AUTO_INCREMENT,
  `p1_user_id` varchar(100) NOT NULL DEFAULT '',
  `p2_user_id` varchar(100) NOT NULL DEFAULT '',
  `p3_user_id` varchar(100) NOT NULL DEFAULT '',
  `p4_user_id` varchar(100) NOT NULL DEFAULT '',
  `player_one_name` varchar(100) DEFAULT NULL,
  `player_two_name` varchar(100) DEFAULT NULL,
  `player_three_name` varchar(100) DEFAULT NULL,
  `player_four_name` varchar(100) DEFAULT NULL,
  `player_one_email` varchar(100) DEFAULT NULL,
  `player_two_email` varchar(100) DEFAULT NULL,
  `player_three_email` varchar(100) DEFAULT NULL,
  `player_four_email` varchar(100) DEFAULT NULL,
  `p1_score` bigint(10) DEFAULT '0',
  `p2_score` bigint(10) DEFAULT '0',
  `p3_score` bigint(10) DEFAULT '0',
  `p4_score` bigint(10) DEFAULT '0',
  `game_name` varchar(255) DEFAULT NULL,
  `players` smallint(1) DEFAULT NULL,
  `turn` varchar(10) DEFAULT NULL,
  `turn_num` smallint(10) DEFAULT '0',
  `layout` longtext,
  `verify` varchar(40) DEFAULT NULL,
  `timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  `message` longtext,
  `tourn` smallint(5) NOT NULL DEFAULT '0',
  `round` smallint(4) NOT NULL DEFAULT '0',
  `tourn_id` varchar(20) NOT NULL DEFAULT '',
  `move_history` longtext NOT NULL,
  `next_turn` varchar(50) NOT NULL DEFAULT '',
  PRIMARY KEY (`id`),
  KEY `tourn` (`tourn`),
  KEY `by_player_one_email` (`player_one_email`(10)),
  KEY `by_player_two_email` (`player_two_email`(10)),
  KEY `by_player_three_email` (`player_three_email`(10)),
  KEY `by_player_four_email` (`player_four_email`(10)),
  KEY `p1_user_id` (`p1_user_id`),
  KEY `p2_user_id` (`p2_user_id`),
  KEY `p3_user_id` (`p3_user_id`),
  KEY `p4_user_id` (`p4_user_id`),
  KEY `turn` (`turn`),
  KEY `verify` (`verify`),
  KEY `next_turn` (`next_turn`),
  KEY `timestamp` (`timestamp`),
  KEY `round` (`round`),

) ENGINE=MyISAM DEFAULT CHARSET=latin1;

最佳答案

如果没有时间戳条件的查询运行得很快,理论上,将其作为子查询应该运行得同样快。假设性能差异是由查询优化器中的错误引起的,这应该具有相同的性能:

SELECT * FROM (query without timestamp condition) t WHERE timestamp > 20130201

当然这只是猜测。在不知道表、查询和查询的解释计划的情况下,不可能对问题给出明确的答案。

更新:现在我们有了表描述和解释计划,我们看到查询正在使用 timestamp 列上定义的索引。显然这个索引不是这个查询的好选择,因为查询最终检查了超过 51000 行。你可以tell MySQL that a different index might be better使用索引提示。

例如,这应该使用用户 ID 上的索引,它应该像查询一样执行而不限制 timestamp:

SELECT ... from game USE INDEX (p1_user_id,p2_user_id,p3_user_id,p4_user_id)
WHERE ...

或者,您可以要求 MySQL 忽略 timestamp 上的索引,因此它应该使用其他更合适的索引:

SELECT ... from game IGNORE INDEX (timestamp) WHERE ...

查询可能会受益于创建多列索引。

关于MySQL 查询缓慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15600790/

相关文章:

mysql - 何时修复 MYSQL 中的自增间隙

php - 如何将 mysql 记录传递给 php 并确保它是 UTF-8 编码

mysql - 提取具有多行的组

performance - 检测 QCView 中的 Quartz Composition 是通过软件还是硬件渲染

performance - 究竟什么是委托(delegate)?

php - Laravel 5 更新返回旧关系

MySQL 无法写入临时目录

c++ - GCC 4.6.2 内联行为

javascript - ES6 将可迭代对象转换为数组时间复杂度

sql - 性能查询 PostgreSQL