对于读写密集型应用程序,在 mysql 中有效存储 url 的最佳方法是什么?
我将存储超过 500,000 个网址(全部以 http://或 https://开头。没有其他协议(protocol))并保存整个 url (http://example.com/path/?variable=a ) 放在一列中似乎在很大程度上是多余的,因为相同的域名和路径将多次保存到 mysql。
因此,最初,我想将它们分解(即域、路径和变量等)以消除冗余。但是看到有帖子说不推荐。对此有什么想法吗?
此外,应用程序通常必须在没有主键的情况下检索 url,这意味着它必须搜索文本以检索 url。 URL 可以被索引,但我想知道如果它们都在 innodb 下被索引(没有全文索引),那么存储整个 url 和分解的 url 之间会有多大的性能差异。
broken-down-url 必须经过额外的步骤来组合它们。此外,这意味着我必须从不同的表(协议(protocol)、域、路径、变量)中检索数据 4 次,但它也会使每行中存储的数据更短,并且每个表中的行也会更少。这可能会加快这个过程吗?
最佳答案
我已经广泛处理过这个问题,我的一般理念是使用使用频率方法。这很麻烦,但它可以让您对数据进行一些出色的分析:
CREATE TABLE URL (
ID integer unsigned NOT NULL PRIMARY KEY AUTO_INCREMENT,
DomainPath integer unsigned NOT NULL,
QueryString text
) Engine=MyISAM;
CREATE TABLE DomainPath (
ID integer unsigned NOT NULL PRIMARY KEY AUTO_INCREMENT,
Domain integer unsigned NOT NULL,
Path text,
UNIQUE (Domain,Path)
) Engine=MyISAM;
CREATE TABLE Domain (
ID integer unsigned NOT NULL PRIMARY KEY AUTO_INCREMENT,
Protocol tinyint NOT NULL,
Domain varchar(64)
Port smallint NULL,
UNIQUE (Protocol,Domain,Port)
) Engine=MyISAM;
作为一般规则,您将在单个域上具有相似的路径,但每个路径具有不同的查询字符串。
我最初设计它是为了让所有部分都在一个表(协议(protocol)、域、路径、查询字符串)中建立索引,但我认为上面的内容占用的空间更少,更有助于从中获取更好的数据。
text 往往很慢,因此您可以在使用一段时间后将“Path”更改为 varchar。大多数服务器在 URL 大约 1K 后就死机了,但我见过一些大服务器,宁愿不丢失数据也会犯错。
您的检索查询很麻烦,但如果您在代码中将其抽象化,没问题:
SELECT CONCAT(
IF(D.Protocol=0,'http://','https://'),
D.Domain,
IF(D.Port IS NULL,'',CONCAT(':',D.Port)),
'/', DP.Path,
IF(U.QueryString IS NULL,'',CONCAT('?',U.QueryString))
)
FROM URL U
INNER JOIN DomainPath DP ON U.DomainPath=DP.ID
INNER JOIN Domain D on DP.Domain=D.ID
WHERE U.ID=$DesiredID;
如果端口号不是标准的(http 非 80,https 非 443),则存储它,否则将其存储为 NULL 以表示不应包含它。 (您可以将逻辑添加到 MySQL,但它会变得更丑陋。)
我总是(或从不)从路径中去掉“/”以及“?”来自 QueryString 以节省空间。只有损失才能区分
http://www.example.com/
http://www.example.com/?
如果它很重要,那么我会改变你的策略,从不剥离它,只包含它。技术上,
http://www.example.com
http://www.example.com/
都是一样的,所以去除 Path 斜杠总是可以的。
因此,要解析:
http://www.example.com/my/path/to/my/file.php?id=412&crsource=google+adwords
我们将在 PHP 中使用类似 parse_url 的东西来生成:
array(
[scheme] => 'http',
[host] => 'www.example.com',
[path] => '/my/path/to/my/file.php',
[query] => 'id=412&crsource=google+adwords',
)
然后您将检查/插入(使用适当的锁,未显示):
SELECT D.ID FROM Domain D
WHERE
D.Protocol=0
AND D.Domain='www.example.com'
AND D.Port IS NULL
(如果不存在)
INSERT INTO Domain (
Protocol, Domain, Port
) VALUES (
0, 'www.example.com', NULL
);
然后我们的 $DomainID 继续......
然后插入DomainPath:
SELECT DP.ID FORM DomainPath DP WHERE
DP.Domain=$DomainID AND Path='/my/path/to/my/file.php';
(如果不存在,同样插入)
然后我们的 $DomainPathID 继续......
SELECT U.ID FROM URL
WHERE
DomainPath=$DomainPathID
AND QueryString='id=412&crsource=google+adwords'
并在必要时插入。
现在,让我注意重要,上述方案对于高性能站点来说会很慢。您应该修改所有内容以使用某种散列来加速 SELECT。简而言之,该技术如下:
CREATE TABLE Foo (
ID integer unsigned PRIMARY KEY NOT NULL AUTO_INCREMENT,
Hash varbinary(16) NOT NULL,
Content text
) Type=MyISAM;
SELECT ID FROM Foo WHERE Hash=UNHEX(MD5('id=412&crsource=google+adwords'));
为了简单起见,我特意从上面删除了它,但是将一个 TEXT 与另一个 TEXT 进行比较以进行选择很慢,并且会中断非常长的查询字符串。也不要使用固定长度的索引,因为那样也会中断。对于精度很重要的任意长度字符串,哈希失败率是可以接受的。
最后,如果可以的话,执行 MD5 哈希客户端以节省将大 blob 发送到服务器以执行 MD5 操作。大多数现代语言都支持内置 MD5:
SELECT ID FROM Foo WHERE Hash=UNHEX('82fd4bcf8b686cffe81e937c43b5bfeb');
但我离题了。
关于mysql - 在 mysql 中为读写密集型应用程序存储 url 的最佳方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5147867/
我需要在客户计算机上运行Ruby应用程序。通常需要几天才能完成(复制大备份文件)。问题是如果启用sleep,它会中断应用程序。否则,计算机将持续运行数周,直到我下次访问为止。有什么方法可以防止执行期间休眠并让Windows在执行后休眠吗?欢迎任何疯狂的想法;-) 最佳答案 Here建议使用SetThreadExecutionStateWinAPI函数,使应用程序能够通知系统它正在使用中,从而防止系统在应用程序运行时进入休眠状态或关闭显示。像这样的东西:require'Win32API'ES_AWAYMODE_REQUIRED=0x0
对于具有离线功能的智能手机应用程序,我正在为Xml文件创建单向文本同步。我希望我的服务器将增量/差异(例如GNU差异补丁)发送到目标设备。这是计划:Time=0Server:hasversion_1ofXmlfile(~800kiB)Client:hasversion_1ofXmlfile(~800kiB)Time=1Server:hasversion_1andversion_2ofXmlfile(each~800kiB)computesdeltaoftheseversions(=patch)(~10kiB)sendspatchtoClient(~10kiBtransferred)Cl
我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i
Rackup通过Rack的默认处理程序成功运行任何Rack应用程序。例如:classRackAppdefcall(environment)['200',{'Content-Type'=>'text/html'},["Helloworld"]]endendrunRackApp.new但是当最后一行更改为使用Rack的内置CGI处理程序时,rackup给出“NoMethodErrorat/undefinedmethod`call'fornil:NilClass”:Rack::Handler::CGI.runRackApp.newRack的其他内置处理程序也提出了同样的反对意见。例如Rack
我想用ruby编写一个小的命令行实用程序并将其作为gem分发。我知道安装后,Guard、Sass和Thor等某些gem可以从命令行自行运行。为了让gem像二进制文件一样可用,我需要在我的gemspec中指定什么。 最佳答案 Gem::Specification.newdo|s|...s.executable='name_of_executable'...endhttp://docs.rubygems.org/read/chapter/20 关于ruby-在Ruby中编写命令行实用程序
我构建了两个需要相互通信和发送文件的Rails应用程序。例如,一个Rails应用程序会发送请求以查看其他应用程序数据库中的表。然后另一个应用程序将呈现该表的json并将其发回。我还希望一个应用程序将存储在其公共(public)目录中的文本文件发送到另一个应用程序的公共(public)目录。我从来没有做过这样的事情,所以我什至不知道从哪里开始。任何帮助,将不胜感激。谢谢! 最佳答案 无论Rails是什么,几乎所有Web应用程序都有您的要求,大多数现代Web应用程序都需要相互通信。但是有一个小小的理解需要你坚持下去,网站不应直接访问彼此
我尝试运行2.x应用程序。我使用rvm并为此应用程序设置其他版本的ruby:$rvmuseree-1.8.7-head我尝试运行服务器,然后出现很多错误:$script/serverNOTE:Gem.source_indexisdeprecated,useSpecification.Itwillberemovedonorafter2011-11-01.Gem.source_indexcalledfrom/Users/serg/rails_projects_terminal/work_proj/spohelp/config/../vendor/rails/railties/lib/r
刚入门rails,开始慢慢理解。有人可以解释或给我一些关于在application_controller中编码的好处或时间和原因的想法吗?有哪些用例。您如何为Rails应用程序使用应用程序Controller?我不想在那里放太多代码,因为据我了解,每个请求都会调用此Controller。这是真的? 最佳答案 ApplicationController实际上是您应用程序中的每个其他Controller都将从中继承的类(尽管这不是强制性的)。我同意不要用太多代码弄乱它并保持干净整洁的态度,尽管在某些情况下ApplicationContr
从给定URL下载文件并立即将其上传到AmazonS3的更直接的方法是什么(+将有关文件的一些信息保存到数据库中,例如名称、大小等)?现在,我既不使用Paperclip,也不使用Carrierwave。谢谢 最佳答案 简单明了:require'open-uri'require's3'amazon=S3::Service.new(access_key_id:'KEY',secret_access_key:'KEY')bucket=amazon.buckets.find('image_storage')url='http://www.ex
我正在编写一个小脚本来定位aws存储桶中的特定文件,并创建一个临时验证的url以发送给同事。(理想情况下,这将创建类似于在控制台上右键单击存储桶中的文件并复制链接地址的结果)。我研究过回形针,它似乎不符合这个标准,但我可能只是不知道它的全部功能。我尝试了以下方法:defauthenticated_url(file_name,bucket)AWS::S3::S3Object.url_for(file_name,bucket,:secure=>true,:expires=>20*60)end产生这种类型的结果:...-1.amazonaws.com/file_path/file.zip.A