- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我在我的 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_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
这意味着我刚刚摆脱了文件排序,尽管我在 where 子句上丢失了索引。
查询似乎返回 15,000 条记录(由于 in),然后对它们进行排序并选择最后 50 条。至于我的问题 - 排序 15,000 条记录的效率怎么可能低于扫描 1.5M 表并搜索 15,000 条记录的效率?排序不应该是一项如此困难的任务,而搜索要困难得多(没有索引!)我错过了什么?
附表索引:
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 必须打乱表中的所有列。此重构中的子查询只是提供了您想要的五十个 id
值。它仍然需要对它们进行排序,但是对一堆整数进行排序比对一堆行进行排序要快。
SELECT id
FROM items
WHERE owner_id IN (1, 2, 3, 4, 5, 6, 7, 8)
ORDER BY id DESC
LIMIT 50
外部查询为这五十个 id 中的每一个检索整行,这应该相对较快。
这里有一点需要注意。
WHERE owner_id BETWEEN 1 AND 8
对于 MySQL 来说比
更容易满足WHERE owner_id IN (1, 2, 3, 4, 5, 6, 7, 8)
因为服务器可以对 owner_id
上的索引进行单范围扫描。您可能无法在所有情况下都使用 BETWEEN
,但如果可以,请使用。
如果此查询对性能至关重要,您可以尝试在
上创建复合索引(owner_id, id)
看看它是否大大加快了查询速度。
关于Mysql - 为什么 FileSort 需要比实际提取时间更长的时间?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25364138/
我有一个类似于以下内容的查询: SELECT * FROM tablename WHERE condition = 1 ORDER BY id LIMIT 1000; id是主键。我有一个索引 con
我有一些推荐表 CREATE TABLE IF NOT EXISTS `testimonials` ( `id` int(11) NOT NULL AUTO_INCREMENT, `title
我有以下查询: SELECT * FROM shop_user_member_spots WHERE delete_flag = 0 ORDER BY date_spotte
我正在尝试创建一个选择查询,但是当我使用解释查询时,mysql 总是额外使用“使用文件排序”。 我尝试了最简单的查询,但问题并没有消失。我的表“Partidas”的结构是: CREATE TABLE
我有一个包含日期时间列的表,我按该列进行排序。无论我做什么,我总是从 EXPLAIN 中得到“使用哪里;使用文件排序”。 有没有办法让日期时间列上的 ORDER BY 不使用文件排序? 查询非常简单,
我在我的 Mysql 数据库上运行了一个 sql 查询。我有一张包含 150 万条记录的表。我正在尝试根据项目的创建者获取最近创建的 50 个项目。 这里是查询: SELECT * FROM `ite
mysql-5.6.24-win32.1432006610 我有两个用户消息表。 TMessageBody (id, body) 存储消息正文。 TMessage (id, uid, folderId
你好,这个查询正在生成这个解释,考虑到我为两列都设置了索引,这很奇怪 '1', 'SIMPLE', 'vtr_video_transactions', 'ALL', 'user_standard,us
我有一个简单的表格-> id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY by_id INT UNSIGNED NOT NULL posted_o
我有一个像这样的表结构 comment_id primary key comment_content comment_author comment_author_url 当我像 这样触发查询时 exp
我有一个包含 40,000,000 行的表,我正在尝试优化我的查询,因为花费的时间太长。 首先,这是我的 table : 创建表 恢复 ( yearMonth char(6) DEFAULT NULL
我正在尝试优化使用 order by 子句的 sql 查询。当我使用 EXPLAIN 时,查询总是显示“使用文件排序”。我正在将此查询应用于一个群组讨论论坛,其中有用户附加到帖子的标签。 这是我正在使
我正在尝试优化此查询: SELECT `posts`.* FROM `posts` INNER JOIN `posts_tags` ON `posts`.id = `posts_tags`.
子查询1: SELECT * from big_table where category = 'fruits' and name = 'apple' order by yyyymmdd desc 解释
我有一个查询比这个查询稍微复杂一点(获得最便宜的价格),但这代表了性能问题。因此查询不能更改。 我尝试创建不同的索引来加快排序速度,但没有运气。 需要什么索引才能更快地获得这个 1.4 秒的持久查询?
我有一张带有日期时间 (DATE) 和位 (PUBLIC) 的 Cars 表。 现在我想获取按 DATE 和 PUBLIC = 1 排序的行,所以我使用: select c.* from Ca
我有如下 2 个表: CREATE TABLE `ox_campaigns` ( `
我正在尝试使用 EXPLAIN 优化此 mysql 查询。有人可以帮我解决这个问题吗? EXPLAIN SELECT * FROM keyword WHERE keyword LIKE "panaso
有表格: CREATE TABLE `deal_keyword` ( `deal_id` int(11) unsigned NOT NULL default '0', `keyword_id`
我将用这样的查询来解释自己:(post_id= PRIMARY, blog_id=index ) SELECT post_id FROM posts WHERE blog_id IN (2,3,...
我是一名优秀的程序员,十分优秀!