优化MYSQL大表Select查询

Tad*_* V. 7 mysql

给定表格:

CREATE TABLE `sample` (
    `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
    `vendorid` VARCHAR(45) NOT NULL,
    `year` INT(10) NOT NULL,
    `title` TEXT NOT NULL,
    `description` TEXT NOT NULL
    PRIMARY KEY (`id`) USING BTREE
)
Run Code Online (Sandbox Code Playgroud)

表规模:700万以上除 id 外,所有字段都不是唯一的

简单查询:

SELECT * FROM sample WHERE title='milk'
Run Code Online (Sandbox Code Playgroud)

需要 45 到 60 秒才能完成。

尝试在标题和描述上放置唯一索引,但收到 1170 错误。

我该如何优化它?将非常感谢您的建议。

And*_*yer 12

如果您预计不会有很多行,或者您只想返回少量行,那么非唯一索引title就是最佳选择。由于此列是一种TEXT数据类型,因此您需要以某种方式限制长度,我选择了 100。

create index sample_idx01 on sample (title (100))
Run Code Online (Sandbox Code Playgroud)

默认情况下,索引不需要唯一性。


J.D*_*.D. 7

title字段上的索引可能会有所帮助,就像安德鲁提到的那样,因为是的,您通常希望对查询的谓词建立索引。但是,您的示例查询引起我注意的另一个问题是它正在使用SELECT *.

当您使用 时SELECT *,您使用的反模式可能会影响查询性能并导致使用次优查询计划。我的猜测(需要查看EXPLAIN ANALYZE)是您当前获得的查询计划是针对整个聚集索引(整个表)的扫描。即使在 上添加二级索引之后,情况可能仍然如此title

相反,您应该只明确列出SELECT该给定查询实际需要的列,并可能将它们添加到辅助索引键中(title在定义中的列之后)。或者,如果此查询非常常用并且确实需要选择所有列,则您应该将title其作为聚集(主)索引的一部分,然后该索引将自动包含聚集在 上的表​​的所有字段title

但无论如何,您应该停止使用SELECT *并始终明确列出您需要的列(即使它是表的所有列),以提高查询的可读性和可维护性。

  • @塔达斯V。听起来您实际上看到了类似的结果,并且现在可能看到了相同的查询计划。这不是您所做的测试的粒度。我不确定您此时是否进行了其他更改,例如 Andrew 的建议,但我的观点是使用“SELECT *”可能会导致完整索引扫描,即使是在聚集索引而不是辅助索引上,这会导致然后让你的二级索引变得毫无用处,并最大限度地减少你获得最佳计划的机会。它并不总是发生,但实际上是可能的。您可以使用“EXPLAIN ANALYZE”来比较查询计划以进行测试。 (2认同)