Mysql SQL提高效率:限制文件排序的数量

Mysql SQL提高效率:限制文件排序的数量,mysql,sql,mariadb,Mysql,Sql,Mariadb,我将用这样一个查询来解释我自己:(post\u id=PRIMARY,blog\u id=index) 更新:in()中的ID可能很多。 如果DB使用blog_id作为查询的键,则必须进行文件排序,因为索引如下所示: (blog_id,post_id)-> (1,55) (1,59) (1,69) (2,57) (2,71) (2,72) (3,12) 如果只搜索一个id blog_id=2而不是IN(),则不需要进行任何文件排序,因为所有匹配项都已按顺序排列 我认为它正在发生的问题,不

我将用这样一个查询来解释我自己:(post\u id=PRIMARY,blog\u id=index)

更新:in()中的ID可能很多。 如果DB使用blog_id作为查询的键,则必须进行文件排序,因为索引如下所示:

(blog_id,post_id)-> (1,55) (1,59) (1,69) (2,57) (2,71) (2,72) (3,12)
如果只搜索一个id blog_id=2而不是IN(),则不需要进行任何文件排序,因为所有匹配项都已按顺序排列

我认为它正在发生的问题,不是100%确定,只是通过查看查询执行时间,是如果我添加一个限制10,有效的方法是只捕获和文件排序每个blog_id索引键匹配的最后10个id,可能它已经这样做了,但看起来像是按(2,3,4)顺序的post_id DESC LIMIT 10,它存储数千个ID,而不是30个

我希望我是大错特错,因为如果我不是,那就是一个可怕的低效错误。
如果我是对的,我能做些什么发动机或改变吗?甚至改变数据库。目前我使用的是10.1.13-MariaDB,表是InnoDB。不幸的是,MySQL没有一个索引可以让你做你想做的事情

但是,您可以重写现有查询并使用现有索引:

SELECT p.post_id
FROM ((SELECT post_id
       FROM posts
       WHERE blog_id = 2
       ORDER BY post_id DESC
       LIMIT 10
      ) UNION ALL
      (SELECT post_id
       FROM posts
       WHERE blog_id = 3
       ORDER BY post_id DESC
       LIMIT 10
      )
     ) p
ORDER BY post_id DESC
LIMIT 10;

每个子查询都将使用索引。对20个元素进行排序非常快。

不幸的是,MySQL没有一个索引可以让您随心所欲

但是,您可以重写现有查询并使用现有索引:

SELECT p.post_id
FROM ((SELECT post_id
       FROM posts
       WHERE blog_id = 2
       ORDER BY post_id DESC
       LIMIT 10
      ) UNION ALL
      (SELECT post_id
       FROM posts
       WHERE blog_id = 3
       ORDER BY post_id DESC
       LIMIT 10
      )
     ) p
ORDER BY post_id DESC
LIMIT 10;

每个子查询都将使用索引。对20个元素进行排序非常快。

查看
解释选择…
;看看上面是否写着“文件排序”

执行以下操作以获取详细信息,即使对于小数据集也是如此:

FLUSH STATUS;
SELECT ...;
SHOW SESSION STATUS LIKE 'Handler%';
您确实需要
索引(blog\u id,post\u id)
。如果您使用的是InnoDB,并且该表

PRIMARY KEY(post_id),
INDEX(blog_id)
那么你就有了综合指数。这是因为每个二级索引都隐式包含PK的列

由于您正在使用MariaDB,请查看是否会执行您要求的其他操作

当优化器看到以下情况时:

WHERE blog_id IN (2,3)
ORDER BY post_id DESC LIMIT 10
它既有
索引(blog\u id)
又有
索引(post\u id)
,它可以根据有限的统计数据决定走哪条路:

计划A:在blog_id+filesort上进行筛选,或
方案B:按id后序扫描,希望很快找到10行


两者都有风险。如果大多数或所有行都是(2,3),计划A将有一个大排序。当匹配行少于10行时,计划B将扫描整个表(或索引)。

查看
解释选择…
;看看上面是否写着“文件排序”

执行以下操作以获取详细信息,即使对于小数据集也是如此:

FLUSH STATUS;
SELECT ...;
SHOW SESSION STATUS LIKE 'Handler%';
您确实需要
索引(blog\u id,post\u id)
。如果您使用的是InnoDB,并且该表

PRIMARY KEY(post_id),
INDEX(blog_id)
那么你就有了综合指数。这是因为每个二级索引都隐式包含PK的列

由于您正在使用MariaDB,请查看是否会执行您要求的其他操作

当优化器看到以下情况时:

WHERE blog_id IN (2,3)
ORDER BY post_id DESC LIMIT 10
它既有
索引(blog\u id)
又有
索引(post\u id)
,它可以根据有限的统计数据决定走哪条路:

计划A:在blog_id+filesort上进行筛选,或
方案B:按id后序扫描,希望很快找到10行


两者都有风险。如果大多数或所有行都是(2,3),计划A将有一个大排序。当匹配行少于10行时,计划B将扫描整个表(或索引)。

嗯,IN()ID可以是数百个,它们是动态的,它们会改变,这就是一个例子。从我的角度来看,我认为我所说的很简单,而且在技术上是可能的,所以我不明白为什么没有做到,在我的头脑中没有意义。顺便说一下,我现在和MariaDB在一起,他们有了新的表格引擎。没有任何可能性吗?你说没有一个索引能做到这一点,也许我对索引顺序的理解是错误的?因为索引对我来说是正确的,所以我在这里看到的问题是引擎搜索的方式。PD:by“而且它们是动态的,它们是变化的”我的意思是数量的变化,可以进行分类,但正如我所说的,可以有很多ID。UNION方法适合于少量博客ID;对于一个大的数字(N)来说不是很好,
UNION
的开销加上tmp表将是10*N行。@Vixxs。只能回答你提出的问题。您的问题有2个或3个ID。如果你有很多(比如成百上千),那么中的
可能不是最好的方法。你是对的。为我辩护,我想说这两个例子表明ID的数量是可变的,这暗示了数量可能更大,它们就是一个例子。但正如我所说的,你是对的,我仍然可以选择这个答案或任何更正确地回答未更新答案的答案。从我的角度来看,我认为我所说的很简单,而且在技术上是可能的,所以我不明白为什么没有做到,在我的头脑中没有意义。顺便说一下,我现在和MariaDB在一起,他们有了新的表格引擎。没有任何可能性吗?你说没有一个索引能做到这一点,也许我对索引顺序的理解是错误的?因为索引对我来说是正确的,所以我在这里看到的问题是引擎搜索的方式。PD:by“而且它们是动态的,它们是变化的”我的意思是数量的变化,可以进行分类,但正如我所说的,可以有很多ID。UNION
方法适合于少量博客ID;对于一个大的数字(N)来说不是很好,
UNION
的开销加上tmp表将是10*N行。@Vixxs。只能回答你提出的问题。您的问题有2个或3个ID。如果你有很多(比如成百上千),那么中的
可能不是最好的方法。你是对的。为我辩护,我想说这两个例子表明ID的数量