我正在构建一个动态查询来从我的数据库中选择已删除的域名。目前有十几行,但我很快就会得到数据,这些数据的记录最多可达500,000行。
架构只是一个包含4列的表:
CREATE TABLE `DroppedDomains` (
`domainID` int(11) NOT NULL AUTO_INCREMENT,
`DomainName` varchar(100) COLLATE utf8_unicode_ci DEFAULT NULL,
`DropDate` date DEFAULT NULL,
`TLD` varchar(5) COLLATE utf8_unicode_ci DEFAULT NULL,
PRIMARY KEY (`domainID`)
) ENGINE=MyISAM AUTO_INCREMENT=8 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
我没有创建架构,这是实时数据库架构。以下是示例数据:
我可能构建了下面最复杂的查询类型。标准如下:
选择任意数量的域
- 以“开始”一词开头
- 以“结束”一词结尾
- 在域名
的任何位置包含“containsThis”字样- 在域名
的任何位置包含“ContainsThisToo”字样- 包含至少一位数字
- 域名必须至少为49个字符。多字节需要计数 作为一个角色(我使用CHAR_LENGTH )。
- 域名必须至少少于65个字符。
- TLD必须是'org'
- DropDate需要晚于
醇>2009-11-01
到目前为止,这是我的查询:
SELECT
*
FROM
DroppedDomains
WHERE
1=1
AND DomainName LIKE 'starts%ends'
AND DomainName LIKE '%containsThis%'
AND DomainName LIKE '%containsThisToo%'
AND DomainName LIKE '%-%'
AND DomainName REGEXP '[0-9]'
AND CHAR_LENGTH(DomainName) > 49
AND CHAR_LENGTH(DomainName) < 65
AND TLD = 'org'
AND DropDate > '2009-11-01'
以下是我的问题
考虑到我有50万行,如果我将TLD
列设置为自己的表,并将TLD
列设为外键,那么它的性能会非常有益吗? ?只有5个TLD(com,net,org,info,biz)。我意识到现实世界中有更多TLD,但此应用程序只有5个。用户无法指定自己的TLD。
我知道REGEXP
和500,000行可能是灾难的秘诀。无论如何我可以避免REGEXP
吗?
我可以对查询进行其他任何优化吗?像合并LIKE
或使用其他功能,如可能INSTR
?我应该实现任何特定类型的缓存机制吗?
答案 0 :(得分:3)
如果LIKE模式以常量前缀开头,并且您在该字段上有索引,那么索引可用于快速查找以前缀开头的行。幸运的是,你在这里遇到了这种情况:
AND DomainName LIKE 'starts%ends'
如果只有少数值以starts
开头,则可以非常快速地找到这些行,并且仅针对这些行测试其他表达式。您可以通过运行EXPLAIN SELECT ...
来检查是否使用了索引。
答案 1 :(得分:1)
您应该根据您计划使用的查询来规划要创建的索引。
如果您使用的唯一查询是您提到的复杂查询,那么Mark的建议(关于DomainName的索引)是最好的。
关于TLD
字段的问题1:
如果您真的只有少量(如5个)选项,并且您不打算使用所有可用的tld,则可以使用ENUM
type。
CREATE TABLE(
....
tld ENUM('com', 'net', 'org', 'info', 'biz')
)