【问题标题】:Something wrong with indexes索引有问题
【发布时间】:2018-01-05 18:09:44
【问题描述】:

我有两张桌子:

第一:

CREATE TABLE `dialog_projects` (
`id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
`creator_user_id` INT(11) UNSIGNED NOT NULL,
`add_users_allowed` INT(1) NULL DEFAULT '1',
`dlg_name` VARCHAR(200) NOT NULL,
`dlg_date` DATETIME NOT NULL,
PRIMARY KEY (`id`),
INDEX `dialog_projects_creator_user_id_ind` (`creator_user_id`),
INDEX `dialog_projects_add_users_allowed_ind` (`add_users_allowed`),
INDEX `dialog_projects_dlg_date_ind` (`dlg_date`)
)
COLLATE='utf8_general_ci'
ENGINE=InnoDB
AUTO_INCREMENT=220094
/*!50100 PARTITION BY KEY (id)
PARTITIONS 10  */;

第二:

CREATE TABLE `dialog_users` (
`dialog_projects_id` INT(11) UNSIGNED NOT NULL,
`user_id` INT(11) UNSIGNED NOT NULL,
`num_new_msgs` INT(11) UNSIGNED NOT NULL,
`accepted` TINYINT(1) NULL DEFAULT '0',
`last_visit` DATETIME NOT NULL,
PRIMARY KEY (`dialog_projects_id`, `user_id`, `num_new_msgs`),
INDEX `dialog_projects_accepted_ind` (`accepted`),
INDEX `dialog_projects_last_visit_ind` (`last_visit`)
)
COLLATE='utf8_general_ci'
ENGINE=InnoDB
/*!50100 PARTITION BY HASH (dialog_projects_id + user_id + num_new_msgs)
PARTITIONS 10  */;

此查询执行大约 5,5 秒,但没有“order by du.num_new_msgs desc” - 需要 0,005 秒。如何提高速度?怎么了?

#explain 
select SQL_NO_CACHE dp.id
from `dialog_users` as du 
left join `dialog_projects` as dp
 on (du.dialog_projects_id = dp.id) 
where dp.id > 300 and du.num_new_msgs > -1 
    and dp.add_users_allowed = 0 and du.user_id = 10990 

order by du.num_new_msgs desc, dp.id desc 
limit 10

这里解释一下:

"id"    "select_type"   "table" "type"  "possible_keys" "key"   "key_len"   "ref"   "rows"  "Extra"
"1" "SIMPLE"    "dp"    "ref"   "PRIMARY,dialog_projects_add_users_allowed_ind" "dialog_projects_add_users_allowed_ind" "5" "const" "100246"    "Using where; Using index; Using temporary; Using filesort"
"1" "SIMPLE"    "du"    "ref"   "PRIMARY"   "PRIMARY"   "8" "sport-event.dp.id,const"   "1" "Using where; Using index"

谢谢

【问题讨论】:

  • 可以升级 MySQL 吗?最近的版本有更好的查询规划器。
  • 我升级了 mysql 但后来。我优化表,而是通过在 where 块中创建一个子句进行排序。这允许将查询时间减少到 0.00 秒,但这不是我想要的。是否可以优化查询离开 "order by du.num_new_msgs" ?

标签: mysql mysql-5.1


【解决方案1】:

为什么将ORDER BY 子句放在LIMIT 子句之前会降低性能?因为没有ORDER BY,MySQL 查询引擎只需要返回十个方便的行,然后就可以停止了。对于ORDER BY,它需要检查结果集中的每一行以找到您想要的。

您的查询说明了这一点。为了清楚起见,我对条款进行了重新排序。

 where dp.id > 300 and dp.add_users_allowed = 0 
   and du.num_new_msgs > -1 and du.user_id = 10990 

您可以尝试在dialog_projects 上的(add_users_allowed, id) 列上放置一个复合索引。这可能有助于加快对该表的查找。

您似乎正在为一个相对较小的表(300K 行)使用分区。这可能会影响您的查询性能。大多数 MySQL 用户甚至不会考虑对他们的表进行分区,直到他们的行数至少是你的一百倍。然后他们非常仔细地计划查询,因此大多数查询涉及有限数量的分区;希望只有一个。

【讨论】:

  • 添加复合索引并没有使查询更快。无论如何,谢谢。
  • 您的信息很有帮助。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-02-05
  • 2017-01-01
  • 2011-06-18
  • 2013-07-03
  • 2011-04-28
相关资源
最近更新 更多