是否可以在MySQL中为int列的最后一位创建索引?
基于此answer我已根据int列的最后一位数创建了分区
CREATE TABLE partition_test(
textfiled INT,
cltext TEXT,
reindexedAt TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
indexedAt TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
status TINYINT(2),
postId INT)
PARTITION BY HASH(MOD(postId, 10))
PARTITIONS 10;
我正在尝试为postId的最后一位创建一个索引,以优化查询时间。有没有办法做到这一点或者postId上的简单索引就足够了?
尝试失败:
CREATE INDEX postLastDigit USING HASH ON partition_test (MOD(postId, 10));
(1064, u"You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'MOD(postId, 10))' at line 1")
和
CREATE INDEX postLastDigit ON partition_test (MOD(postId, 10));
(1064, u"You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'MOD(postId, 10))' at line 1")
更新 该表有超过100M的行。
我的目标是优化以下查询:
1)
SELECT cltext FROM partition_tables
WHERE postId in (<INT>, <INT>)
AND status IS NOT NULL
2)
SELECT cltext FROM partition_tables
WHERE postId in (<INT>, <INT>)
AND status IS NOT NULL
AND reindexedAt BETWEEN (<DATE>, <DATE>)
MariaDB版本: 10.1.23-MariaDB-9 + deb9u1
答案 0 :(得分:1)
您已使用mariadb
和mysql
标记了自己的问题。如果您使用的是最新版本的MariaDB,则可以使用生成的列进行索引。如果您使用的是MySQL,如果您的MySQL版本至少为5.7,则可以这样做。
如果您使用的是较低版本的MySQL,则可以在表格中创建一个附加列,用于存储每行postId
的最后一位数字,并使用该列进行索引/分区。
这意味着对应用程序代码的更改很少:在插入或更新之前,首先获取postId
的最后一位数字,然后再插入/更新一个字段。作为替代方案,您最终可以使用触发器自动填充该附加列。
答案 1 :(得分:1)
您想要加快哪些查询?如果表上没有任何索引,任何查询都必须扫描整个表!如果你想要速度,首先要看索引。
如果您的查询为SELECT ... WHERE post_id = 123
,则您的分区可能会使其运行速度提高10倍。但INDEX(post_id)
,无论是否进行分区,都会使其运行速度提高数百倍。
请提供SELECTs
,以便我们为您提供帮助。
(好吧,如果你只是玩分区,其他人给你可行的答案。)
“分区修剪”很少比以修剪列开头的合适索引更快。
解决了声明的散列问题后,请报告查询是否比使用索引更快。即使对一个索引进行攻击,我预测分区也不会运行得更快,甚至可能运行得慢一些。
答案 2 :(得分:0)
使用虚拟列。在MariaDB 10.2中,您可以在virtual aka generated column上创建索引,就像这样
CREATE TABLE t (
num int,
last_digit int(1) AS (num % 10) VIRTUAL,
KEY index_last_digit (last_digit)
)
然后你可以在你的查询中使用last_digit,即SELECT ... WHERE last_digit = 1
在旧版本的MariaDB 5.2到10.1中,您需要指定 PERSISTENT 属性而不是VIRTUAL,因为无法对非持久生成的列进行索引。