MySQL 作为键值有序存储
MySQL as key-value ordered store
Docs 说:
Most MySQL indexes (PRIMARY KEY, UNIQUE, INDEX, and FULLTEXT) are stored in B-trees.
所以物理上数据已经按键排序。我需要 MySQL 中具有范围查询支持的键值方案:
SELECT key, value FROM MyTable WHERE key >= key1 and key < key2;
在网络上的许多(大多数)示例中,我看到人们添加 ORDER BY
,即使是在按主键选择时也是如此。
我的问题:
- 这里真的需要 ORDER BY 来让结果始终排序吗?如果是 - 为什么?
- 排序会影响性能还是会被优化掉?
- 如果值不是太大,将值作为复合索引的一部分是否有意义,例如只是数字?
-
SELECT key, value FROM MyTable WHERE key > key1 LIMIT 1;
return 下一个键是否大于 key1,或任何大于 key1 的键?如何可靠地获取 LT、LE、GT、GE 积分查询?
(出于接近 'political' 和工具原因,我在 MySQL 中需要它,然后再移动到其他现有的基于 B+ 树的 KV 存储,我已经选择了最好的一个 LMDB,所以问题是仅关于在 MySQL)
中模拟方案
Is ORDER BY really needed here to get the results always sorted, and if yes - why?
如果没有明确的 ORDER BY
子句,MySQL 可能 碰巧 return 会导致所需的顺序——但这种行为 不能保证并且不能依赖(可能存在破坏行为的边缘情况,或者它可能在未来版本中意外更改而没有任何警告)。
由于您需要始终对结果集进行排序,因此您必须添加一个明确的ORDER BY
子句。
Will sorting affect performance or it will be optimized away?
如果您有一个 覆盖 索引——即一个在复合 (key, value)
上定义——那么您问题中提到的确切查询将能够直接从该索引中检索排序的记录。 MySQL 只需要遍历 B 树数据结构,找到所需的结果范围,然后 return 它找到了什么。
如果您没有覆盖索引,那么一旦 MySQL 找到落在过滤范围内的 key
值(使用索引),它就必须在 table 本身检索每个关联的 value
。由于按磁盘顺序执行此操作更快(以最大限度地减少 IO 抖动),MySQL 可能 不会 使用索引进行排序,而是会在结果。我说 "probably" 是因为优化器可能会在某些边缘情况下做出不同的决定,具体取决于 table 大小、索引基数 and/or 存储引擎。
您始终可以 EXPLAIN
您的查询来查看优化器已决定的执行计划,特别是是否将执行文件排序(当且仅当 Using filesort
出现在Extra
列)。
Will it make sense to make values a part of composite index if they are not too big, e.g. just numbers?
如果您确实想要排序的结果,那么(如上所述)您可能会发现使用覆盖索引进行数据检索会更快;当然,权衡是 insertion/updates 会更慢。 "makes sense" 你的情况将取决于你的应用程序的具体情况。
永远记住 Knuth 的格言:“过早的优化是万恶之源。”我可能会在 没有 覆盖索引的情况下开始,并且仅在性能下降到需要时才添加一个。
Will SELECT key, value FROM MyTable WHERE key > key1 LIMIT 1;
return the next key greater then key1, or any key greater than key1? How to reliably get LT,LE,GT,GE point queries?
LIMIT
在结果集排序后应用(如果有的话)。正如上面第一个项目符号下所解释的,如果没有明确的 ORDER BY
子句,结果将以未定义的顺序 returned;因此,关于您的查询将选择的单个记录,可以说的是它与 "an indeterminate key that is greater than key1
".
有关
要获取大于 key1
的 next 键,您必须添加显式 ORDER BY
子句:
SELECT key, value FROM MyTable WHERE key > key1 ORDER BY key LIMIT 1
对于 "less than" 查询,您显然必须颠倒排序顺序,例如:
SELECT key, value FROM MyTable WHERE key <= key1 ORDER BY key DESC LIMIT 1
Docs 说:
Most MySQL indexes (PRIMARY KEY, UNIQUE, INDEX, and FULLTEXT) are stored in B-trees.
所以物理上数据已经按键排序。我需要 MySQL 中具有范围查询支持的键值方案:
SELECT key, value FROM MyTable WHERE key >= key1 and key < key2;
在网络上的许多(大多数)示例中,我看到人们添加 ORDER BY
,即使是在按主键选择时也是如此。
我的问题:
- 这里真的需要 ORDER BY 来让结果始终排序吗?如果是 - 为什么?
- 排序会影响性能还是会被优化掉?
- 如果值不是太大,将值作为复合索引的一部分是否有意义,例如只是数字?
-
SELECT key, value FROM MyTable WHERE key > key1 LIMIT 1;
return 下一个键是否大于 key1,或任何大于 key1 的键?如何可靠地获取 LT、LE、GT、GE 积分查询?
(出于接近 'political' 和工具原因,我在 MySQL 中需要它,然后再移动到其他现有的基于 B+ 树的 KV 存储,我已经选择了最好的一个 LMDB,所以问题是仅关于在 MySQL)
中模拟方案Is ORDER BY really needed here to get the results always sorted, and if yes - why?
如果没有明确的
ORDER BY
子句,MySQL 可能 碰巧 return 会导致所需的顺序——但这种行为 不能保证并且不能依赖(可能存在破坏行为的边缘情况,或者它可能在未来版本中意外更改而没有任何警告)。由于您需要始终对结果集进行排序,因此您必须添加一个明确的
ORDER BY
子句。Will sorting affect performance or it will be optimized away?
如果您有一个 覆盖 索引——即一个在复合
(key, value)
上定义——那么您问题中提到的确切查询将能够直接从该索引中检索排序的记录。 MySQL 只需要遍历 B 树数据结构,找到所需的结果范围,然后 return 它找到了什么。如果您没有覆盖索引,那么一旦 MySQL 找到落在过滤范围内的
key
值(使用索引),它就必须在 table 本身检索每个关联的value
。由于按磁盘顺序执行此操作更快(以最大限度地减少 IO 抖动),MySQL 可能 不会 使用索引进行排序,而是会在结果。我说 "probably" 是因为优化器可能会在某些边缘情况下做出不同的决定,具体取决于 table 大小、索引基数 and/or 存储引擎。您始终可以
EXPLAIN
您的查询来查看优化器已决定的执行计划,特别是是否将执行文件排序(当且仅当Using filesort
出现在Extra
列)。Will it make sense to make values a part of composite index if they are not too big, e.g. just numbers?
如果您确实想要排序的结果,那么(如上所述)您可能会发现使用覆盖索引进行数据检索会更快;当然,权衡是 insertion/updates 会更慢。 "makes sense" 你的情况将取决于你的应用程序的具体情况。
永远记住 Knuth 的格言:“过早的优化是万恶之源。”我可能会在 没有 覆盖索引的情况下开始,并且仅在性能下降到需要时才添加一个。
Will
SELECT key, value FROM MyTable WHERE key > key1 LIMIT 1;
return the next key greater then key1, or any key greater than key1? How to reliably get LT,LE,GT,GE point queries?
有关LIMIT
在结果集排序后应用(如果有的话)。正如上面第一个项目符号下所解释的,如果没有明确的ORDER BY
子句,结果将以未定义的顺序 returned;因此,关于您的查询将选择的单个记录,可以说的是它与 "an indeterminate key that is greater thankey1
".要获取大于
key1
的 next 键,您必须添加显式ORDER BY
子句:SELECT key, value FROM MyTable WHERE key > key1 ORDER BY key LIMIT 1
对于 "less than" 查询,您显然必须颠倒排序顺序,例如:
SELECT key, value FROM MyTable WHERE key <= key1 ORDER BY key DESC LIMIT 1