2016-04-01 13 views
3

私は記事と呼ばれるテーブルがあります。この表の構造は、id(ユニーク)、カテゴリ(記事のカテゴリ、エンターテインメント)、タイトル(記事のタイトル)、画像(記事の画像URL)、リンク記事)、カウンタ(記事の閲覧数)、dateStamp(記事が公開された日付)。カテゴリに基づいてランダムなエントリを取得する

6つのランダムエンターテインメント記事を印刷したいとします。この簡単な、しかし効率的でない方法は、何かをすることです。

$result = $db->query("SELECT * FROM Articles WHERE category = 'entertainment' ORDER BY RAND() LIMIT 6); 

代わりに、私はそれをより効率的にどうやってやりますか? ORDER BY RAND()の代替案を説明している複数のWebサイトがあることは分かっていますが、これらの選択肢を理解できません。私は私の構造に基づいて理解したい。私は、連想配列をランダムなジェネレータを作成するためにシャッフルすることから複数のものを試しましたが、すべてがうまく動作するようにできなかったので、すべてが欲求不満に終わった。 ORDER BY RAND()を使わずに6つのランダムエンターテインメント記事を印刷するにはどうすればよいですか?

+0

はあなたのテーブルが大きいです(1000以上のエントリを考えてみましょう)?そうでない場合は、すべてのデータを選択し、PHPを使用して結果内にランダムな線をつけることができます。 – Random

+0

@ランダムそれは今大きくはありませんが、将来大きくなるので、私は戻ってそれを修正する必要はありません。 – user2896120

答えて

1

効率的な選択肢の1つは、サブセットのデータを任意の基準(category)で選択することです。この列に追加された索引に注意してください。

SELECT 
    r1.* 
FROM 
    articles AS r1 
    INNER JOIN (SELECT(RAND() * (SELECT MAX(id) FROM articles)) AS id) AS r2 
WHERE 
    r1.id >= r2.id 
    AND r1.category = 'entertainment' 
LIMIT 6; 

ここで例えばデータと詳細(3.2メートル行)と実行計画:

mysql> SELECT COUNT(*) FROM articles; 
+----------+ 
| COUNT(*) | 
+----------+ 
| 3200000 | 
+----------+ 
1 row in set (0.00 sec) 

mysql> SELECT 
    r1.* 
FROM 
    articles AS r1 
    INNER JOIN (SELECT(RAND() * (SELECT MAX(id) FROM articles)) AS id) AS r2 
WHERE 
    r1.id >= r2.id 
    AND r1.category = 'entertainment' 
LIMIT 6; 
+---------+-------------+-----------------------------------------------------------+---------------+ 
| id  | topic  | message             | category  | 
+---------+-------------+-----------------------------------------------------------+---------------+ 
| 3153910 | JAX68VVH3FZ | Sed eu eros. Nam consequat dolor       | entertainment | 
| 3153911 | NIY23HWV0VM | tortor. Nunc commodo auctor velit. Aliquam nisl. Nulla eu | entertainment | 
| 3153912 | LKQ42FRB7LA | mus. Proin vel nisl. Quisque        | entertainment | 
| 3153913 | PFL39VHI9RM | gravida             | entertainment | 
| 3153914 | FGV59TUN9TQ | elit, pellentesque a, facilisis non, bibendum sed,  | entertainment | 
| 3153915 | OWH73EBZ1GW | ligula. Nullam enim. Sed nulla ante, iaculis    | entertainment | 
+---------+-------------+-----------------------------------------------------------+---------------+ 
6 rows in set (0.473 sec) 

mysql> explain extended 
SELECT 
    r1.* 
FROM 
    articles AS r1 
    INNER JOIN (SELECT(RAND() * (SELECT MAX(id) FROM articles)) AS id) AS r2 
WHERE 
    r1.id >= r2.id 
    AND r1.category = 'entertainment' 
LIMIT 6; 
+----+-------------+------------+--------+-----------------+---------+---------+-------+---------+----------+------------------------------+ 
| id | select_type | table  | type | possible_keys | key  | key_len | ref | rows | filtered | Extra      | 
+----+-------------+------------+--------+-----------------+---------+---------+-------+---------+----------+------------------------------+ 
| 1 | PRIMARY  | <derived2> | system | NULL   | NULL | NULL | NULL |  1 |  100 | NULL       | 
| 1 | PRIMARY  | r1   | ref | PRIMARY,cat_IDX | cat_IDX | 768  | const | 1560229 |  100 | Using index condition  | 
| 2 | DERIVED  | NULL  | NULL | NULL   | NULL | NULL | NULL | NULL | NULL  | No tables used    | 
| 3 | SUBQUERY | NULL  | NULL | NULL   | NULL | NULL | NULL | NULL | NULL  | Select tables optimized away | 
+----+-------------+------------+--------+-----------------+---------+---------+-------+---------+----------+------------------------------+ 
4 rows in set (0.00 sec) 

性能の差はより(saginificantあります同じ量のデータに対して通常の場合よりも10倍以上):

mysql> SELECT * FROM articles WHERE category = 'entertainment' ORDER BY RAND() LIMIT 6; 
+---------+-------------+---------------------------------------------------------------------------+---------------+ 
| id  | topic  | message                 | category  | 
+---------+-------------+---------------------------------------------------------------------------+---------------+ 
| 2374491 | PZC33VGM0ML | Duis cursus, diam at pretium aliquet, metus urna convallis erat,   | entertainment | 
| 382306 | RFN88EPE4MI | malesuada fames ac turpis egestas. Aliquam fringilla cursus purus. Nullam | entertainment | 
| 1867986 | KWX30ULB1FR | pede.                  | entertainment | 
| 1528863 | ADX52RRJ3MQ | lacus. Mauris non               | entertainment | 
| 2188208 | AOD82PXQ6FS | diam luctus lobortis. Class aptent taciti sociosqu ad litora    | entertainment | 
| 878426 | ABV08HTB2PG | eu eros. Nam consequat dolor vitae dolor. Donec fringilla. Donec   | entertainment | 
+---------+-------------+---------------------------------------------------------------------------+---------------+ 
6 rows in set (5.726 sec) 

希望します。

+0

あなたの答えをありがとう!私は1つの質問があります、あなたがSELECT r1。*と言うとき、r1は何ですか? – user2896120

+0

また、私には7つのエンターテイメント・エントリーがあります。私は6つのランダムエンターテインメント記事を正確に表示したい、このクエリは時々4,5などを表示しています。番号1-6。 6つの記事を正確に表示したい場合はどうすればいいですか? – user2896120

関連する問題