Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/59.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Mysql-为什么文件排序比实际获取时间长?_Mysql_Database Performance - Fatal编程技术网

Mysql-为什么文件排序比实际获取时间长?

Mysql-为什么文件排序比实际获取时间长?,mysql,database-performance,Mysql,Database Performance,我在Mysql数据库上运行了一个sql查询。 我有一张有150万张唱片的桌子。我正在尝试获取最后50个创建的项目,基于项目的创建者 以下是查询: SELECT * FROM `items` WHERE `items`.`owner_id` IN (1, 2, 3, 4, 5, 6, 7, 8) ORDER BY `items`.`id` DESC LIMIT 50 查询使用的是owner\u id索引,这很有意义。正确的? 显然,使用这个索引几乎需要3秒钟,而使用主索引则需要100毫秒

我在Mysql数据库上运行了一个sql查询。 我有一张有150万张唱片的桌子。我正在尝试获取最后50个创建的项目,基于项目的创建者

以下是查询:

SELECT *
FROM `items`
WHERE `items`.`owner_id`
  IN (1, 2, 3, 4, 5, 6, 7, 8)
ORDER BY `items`.`id`
  DESC LIMIT 50
查询使用的是owner\u id索引,这很有意义。正确的? 显然,使用这个索引几乎需要3秒钟,而使用主索引则需要100毫秒

在运行explain时,我看到以下内容:

1   SIMPLE  items   range   idx_owner   idx_owner   4   NULL    56  Using index condition; Using filesort
但是,当我运行以下查询时:

SELECT *
FROM `items` FORCE INDEX(PRIMARY)
WHERE `items`.`owner_id`
  IN (1, 2, 3, 4, 5, 6, 7, 8)
ORDER BY `items`.`id`
  DESC LIMIT 50
我得到以下解释:

1   SIMPLE  items   index   NULL    PRIMARY 4   NULL    50  Using where
这意味着我刚刚摆脱了filesort,尽管我丢失了where子句的索引

该查询似乎返回15000条记录(由于in),然后对它们进行排序并选择最后50条。 至于我的问题——为什么对15000条记录进行排序比扫描150万张表并搜索15000条记录的效率要低?排序不应该是一项如此困难的任务,而搜索要困难得多(没有索引!)我遗漏了什么

附件-表格索引:

items   0   PRIMARY 1   id  A   1444298 NULL    NULL        BTREE       
items   1   items_a951d5d6  1   slug    A   288859  767 NULL        BTREE       
items   1   category_id_refs_id_3b77a81e    1   category_id A   34  NULL    NULL    YES BTREE       
items   1   origin_id_refs_id_99b3fd12  1   origin_id   A   2   NULL    NULL    YES BTREE       
items   1   parent_id_refs_id_99b3fd12  1   parent_id   A   6   NULL    NULL    YES BTREE       
items   1   name    1   name    A   1444298 NULL    NULL        BTREE       
items   1   idx_owner   1   owner_id    A   722149  NULL    NULL        BTREE       

谢谢

对数千行完整信息进行排序并不像您想象的那么便宜。另外,请注意,
filesort
并不一定意味着对文件系统中的文件进行排序。这意味着需要对派生表进行排序

您正在查看的查询可以进行如下重构,结果很可能会更好

SELECT i.*
  FROM items AS i
  JOIN (
        SELECT id
          FROM items
         WHERE owner_id IN (1, 2, 3, 4, 5, 6, 7, 8)
         ORDER BY id DESC
         LIMIT 50
       ) AS j ON i.id = j.id
 ORDER BY i.id DESC
这是因为原始查询包含
SELECT*
。为了满足这个查询,MySQL必须洗牌表中的所有列。此重构中的子查询只提供了所需的50个
id
值。它仍然需要对它们进行排序,但是排序一组整数比排序一组行要快

        SELECT id
          FROM items
         WHERE owner_id IN (1, 2, 3, 4, 5, 6, 7, 8)
         ORDER BY id DESC
         LIMIT 50
外部查询为这50个ID中的每一个检索整行,这应该相对较快

这里有一些值得注意的地方

WHERE owner_id BETWEEN 1 AND 8 
MySQL将比

WHERE owner_id IN (1, 2, 3, 4, 5, 6, 7, 8)
因为服务器可以对
owner\u id
上的索引执行单个范围扫描。您可能无法在所有情况下都在之间使用
,但如果可以,请使用

如果此查询对性能至关重要,则可以尝试在上创建复合索引

(owner_id, id)

看看它是否能大大加快查询速度。

MySQL仍然使用
中的
进行范围扫描,
EXPLAIN
结果证明了这一点。此外,除了覆盖索引之外,
(owner\u id,id)
上的多列索引也不会有帮助,除非搜索只针对一个owner\u id。不过,这是一个不错的答案。如果MySQL足够聪明(非常了解我们的数据),能够自己进行这些类型的优化(比如子查询)就好了。就在最后一个问题上,我的印象是排序只对row_id(这是一个整数字段)执行操作。为什么查询中的列数会影响排序的性能呢?排序必须对一个表进行排序——包括关键列和正在排序的其他列。表越小=排序越快。可以通过减少行数或列数使表变小。这里我的建议是将多行多列排序转换为多行一列排序。