按指定列对表进行预排序

OHL*_*ÁLÁ 4 mysql innodb myisam order-by alter-table

我有一张表,我总是通过订购一列来获取数据。就我而言,我按 订购datenum。但是,由于排序,选择是如此缓慢。

是否可以在datenum. 此列被定义为唯一的。如果定义为索引,选择会更快吗?

gbn*_*gbn 5

  • 表没有自然的、隐含的或内在的排序
  • 任何订单仅由最外层的 ORDER BY 保证

如果这很慢,那么你可以

  • 使索引覆盖(UNIQUE 约束已经是索引)
  • 使它成为聚集索引(它的性质是覆盖的)


Rol*_*DBA 5

可以对表执行 ORDER BY。

ALTER TABLE ... ORDER BY {columns} ;

根据 MySQL 文档

  • ORDER BY 使您能够以特定顺序创建包含行的新表。请注意,插入和删除后,表不会保持此顺序。此选项主要在您知道大多数情况下主要是按特定顺序查询行时很有用。通过在对表进行重大更改后使用此选项,您可能能够获得更高的性能。在某些情况下,如果表按您稍后要排序的列排序,则可能会使 MySQL 的排序更容易。

  • ORDER BY 语法允许为排序指定一个或多个列名,每个列名后面都可以选择跟随 ASC 或 DESC 以分别指示升序或降序排序顺序。默认为升序。只允许列名作为排序条件;不允许任意表达。

  • ORDER BY 对于包含用户定义的聚集索引(PRIMARY KEY 或 NOT NULL UNIQUE 索引)的 InnoDB 表没有意义。InnoDB 总是根据这样的索引对表行进行排序(如果存在)。

  • 注意:在分区表上使用时,ALTER TABLE ... ORDER BY 仅对每个分区内的行进行排序。

由于 InnoDB 执行双索引查找(一个针对 PRIMARY KEY,然后一个针对内部聚集索引gen_clust_index),在 InnoDB 表上运行 ORDER BY 确实不会给您带来性能提升。

恕我直言,如果 PRIMARY KEY 有一些令人讨厌的东西,比如 8 列

  • 对于 MyISAM,您将拥有出色的查找和范围搜索性能
  • 对于 InnoDB,如果有的话,充其量也只会得到极其微不足道的结果

注意:理论上,如果您执行以下操作,您可能会在 InnoDB 表(称为 mytable)中看到非常非常小的性能差异:

CREATE TABLE mytable_new LIKE mytable;
INSERT INTO mytable_new
SELECT * FROM mytable
ORDER BY {primary-key columns};
ALTER TABLE mytable RENAME mytable_old;
ALTER TABLE mytable_new RENAME mytable;
Run Code Online (Sandbox Code Playgroud)

这将按 rowid 顺序和主键顺序对 gen_clust_index(内部簇索引)进行排序。但是,执行 rowids 的这种内部排序就像将 Lead 变成 gold。处理这些所花费的时间、精力和精力远远超过了任何看似可以购买但永远不会实现的性能优势,因为每个主键查找也会导致 rowid 查找。长话短说除非您只使用 MyISAM,否则不要这样做

这是我对 PRIMARY KEY 中的列使用 ORDER BY 的标准

  • PRIMARY KEY 中有 4 列或更多列
  • 对于具有 n 列的 PRIMARY KEY,列 1 .. n-1 在您的 WHERE 和 GROUP BY 子句中应该是静态的,而列 n 将作为您查询中的范围列
  • 仅使用 MyISAM 存储引擎!!!

警告

我提到 8 列 PRIMARY KEY 的原因是什么?我以前的雇主每月从外部供应商那里发送数十 GB 的只读数据。我在那里了解到 ALTER TABLE...ORDER BY 并将其用于那些 MyISAM 表。由于很多范围查询都是针对 PRIMARY KEY 进行的,查询时间让所有人都震惊,包括我自己。