如果我在 MySQL 数据库中有 1000 行,我知道使用TOP
或LIMIT
使查询更快,但我想知道,默认情况下数据是如何排序的?
以及如何使order by time
orusername
默认情况下,以便使用TOP
orLIMIT
更容易和更快?
如果我在 MySQL 数据库中有 1000 行,我知道使用TOP
或LIMIT
使查询更快,但我想知道,默认情况下数据是如何排序的?
以及如何使order by time
orusername
默认情况下,以便使用TOP
orLIMIT
更容易和更快?
在 InnoDB中,行按主键顺序存储。如果您使用LIMIT
with no ORDER BY
,您将始终获得具有最低主键值的行,即使您以随机顺序插入它们也是如此。
create table foo (id int primary key, x char(1), y int) engine=InnoDB;
insert into foo values (5, 'A', 123);
insert into foo values (9, 'B', 234);
insert into foo values (2, 'C', 345);
insert into foo values (4, 'D', 456);
insert into foo values (1, 'E', 567);
select * from foo;
+----+------+------+
| id | x | y |
+----+------+------+
| 1 | E | 567 |
| 2 | C | 345 |
| 4 | D | 456 |
| 5 | A | 123 |
| 9 | B | 234 |
+----+------+------+
在 MyISAM中,行存储在任何适合的地方。最初,这意味着行被附加到数据文件中,但是当您删除行并插入新行时,删除行留下的空白将被新行重新使用。
create table bar (id int primary key, x char(1), y int) engine=MyISAM;
insert into bar values (1, 'A', 123);
insert into bar values (2, 'B', 234);
insert into bar values (3, 'C', 345);
insert into bar values (4, 'D', 456);
insert into bar values (5, 'E', 567);
select * from bar;
+----+------+------+
| id | x | y |
+----+------+------+
| 1 | A | 123 |
| 2 | B | 234 |
| 3 | C | 345 |
| 4 | D | 456 |
| 5 | E | 567 |
+----+------+------+
delete from bar where id between 3 and 4;
insert into bar values (6, 'F', 678);
insert into bar values (7, 'G', 789);
insert into bar values (8, 'H', 890);
select * from bar;
+----+------+------+
| id | x | y |
+----+------+------+
| 1 | A | 123 |
| 2 | B | 234 |
| 7 | G | 789 | <-- new row fills gap
| 6 | F | 678 | <-- new row fills gap
| 5 | E | 567 |
| 8 | H | 890 | <-- new row appends at end
+----+------+------+
如果您使用 InnoDB,另一个例外情况是您从二级索引而不是从主索引检索行。当您在 EXPLAIN 输出中看到“使用索引”注释时,就会发生这种情况。
alter table foo add index (x);
select id, x from foo;
+----+------+
| id | x |
+----+------+
| 5 | A |
| 9 | B |
| 2 | C |
| 4 | D |
| 1 | E |
+----+------+
如果您有更复杂的连接查询,它会变得更加复杂,因为您将获得按访问的第一个表的默认顺序返回的行(其中“第一个”取决于优化器选择表的顺序),然后连接表中的行将取决于前一个表中行的顺序。
select straight_join foo.*, bar.* from bar join foo on bar.x=foo.x;
+----+------+------+----+------+------+
| id | x | y | id | x | y |
+----+------+------+----+------+------+
| 1 | E | 567 | 5 | E | 567 |
| 5 | A | 123 | 1 | A | 123 |
| 9 | B | 234 | 2 | B | 234 |
+----+------+------+----+------+------+
select straight_join foo.*, bar.* from foo join bar on bar.x=foo.x;
+----+------+------+----+------+------+
| id | x | y | id | x | y |
+----+------+------+----+------+------+
| 5 | A | 123 | 1 | A | 123 |
| 9 | B | 234 | 2 | B | 234 |
| 1 | E | 567 | 5 | E | 567 |
+----+------+------+----+------+------+
底线是最好是明确的:当你使用时LIMIT
,指定一个ORDER BY
.
如何默认按时间或用户名下单,以便使用 TOP 或 LIMIT 更简单快捷?
使用InnoDB作为引擎时,可以设置一个索引(其中的列或集合)为主键。如果这些值是唯一的,则在存储时将按原样进行排序。
如果将常规索引用作查询条件的一部分,或者如果查询从所有行中获取数据,则可以使用常规索引来加快排序速度。如果您的标准使用除您正在排序的字段之外的其他索引,它们将无济于事。
给定下表:
| username (Primary) | time (Index) | country |
这些查询将具有使用索引的排序:
select * from users order by time #Will use the index
select * from users where time between X and Y order by time #Will also use the index
Thise 不会(在大多数情况下......)使用索引进行排序:
select * from users where country = China order by time
它通常按照插入的顺序出现,但你不能依赖它。如果您需要特定的订单,请始终指定它。
将索引添加到“时间”和“用户名”以使其更快,并且只选择您需要的数据。
“默认”顺序未指定(即不可靠)
将 ORDER BY 子句添加到选择以确保。