私はこれを幅広く扱ってきましたが、私の一般的な哲学は使用頻度法を使用することです。面倒ですが、データに対して優れた分析を実行できます。
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;
原則として、単一のドメインには同様のパスがありますが、パスごとに異なるクエリ文字列があります。
私はもともと、すべての部分を1つのテーブル(プロトコル、ドメイン、パス、クエリ文字列)でインデックス付けするように設計しましたが、上記の方がスペースをあまり消費せず、より良いデータを取得するのに役立つと思います。
テキストコード> 遅くなる傾向があるので、使用後に「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/
同じなので、パススラッシュを削除しても問題ありません。
したがって、解析するには:
http://www.example.com/my/path/to/my/file.php?id=412&crsource=google+adwords
parse_url
のようなものを使用します PHPで生成するもの:
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
を高速化するには、ある種のハッシュを使用するようにすべてを変更する必要があります s。要するに、テクニックは次のようなものです:
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ハッシュクライアント側を実行して、MD5操作を実行するためにサーバーに大きなblobを送信する手間を省きます。最新の言語のほとんどは、MD5組み込みをサポートしています:
SELECT ID FROM Foo WHERE Hash=UNHEX('82fd4bcf8b686cffe81e937c43b5bfeb');
しかし、私は逸脱します。