0

MySQL でパフォーマンスの問題があります。データベースには約 400,000 のレコードが含まれており、サイトは Drupal で実行され、すべての列にはインデックスがあります。残念ながら、一部の広告にはすべてのデータが含まれていないため、INNER JOIN の代わりに LEFT JOIN を使用する必要があります。

意見:

CREATE VIEW cases_view AS SELECT 
    n.nid AS nid,
        n.created AS created,
        n.type AS type,
        n.status AS status,
        i.field_adpersonid_value AS field_adpersonid_value,
        f.field_adpersonname_value AS field_adpersonname_value,
        l.field_adpersonfamilyname_value AS field_adpersonfamilyname_value,
        b.field_adpersondateofborn_value AS field_adpersondateofborn_value,
        d.field_adpersondateofdied_value AS field_adpersondateofdied_value,
        p.field_adnewspapergroupname_value AS field_adnewspapergroupname,
        c.field_sbfcompanyname_value AS field_sbfcompanyname_value
FROM
    node n
LEFT JOIN field_data_field_adpersonname f ON (f.entity_id = n.nid)
JOIN field_data_field_adpersonid i ON (i.entity_id = n.nid)
LEFT JOIN field_data_field_adpersonfamilyname l ON (l.entity_id = n.nid)
LEFT JOIN field_data_field_adpersondateofborn b ON (b.entity_id = n.nid)
LEFT JOIN field_data_field_adpersondateofdied d ON (d.entity_id = n.nid)
LEFT JOIN field_data_field_adnewspapergroupname p ON (p.entity_id = n.nid)
LEFT JOIN field_data_field_sbfcompanyname c ON (c.entity_id = n.nid)
WHERE
   n.type = 'advertisement' AND n.status = 1 AND  `p`.`field_adnewspapergroupname_value` <> 'Times Newspaper'

次に、このビュー (php) で次のクエリを使用してデータを検索します。

SELECT DISTINCT v.field_adpersonname_value AS field_adpersonname_value, v.field_adpersonid_value AS field_adpersonid_value, v.field_adpersonfamilyname_value AS field_adpersonfamilyname_value, v.field_adpersondateofborn_value AS field_adpersondateofborn_value, v.field_adpersondateofdied_value AS field_adpersondateofdied_value, v.field_sbfcompanyname_value AS field_sbfcompanyname_value
FROM 
cases_view v
WHERE  (v.field_adpersonname_value LIKE 'Sample name%' ESCAPE '\\') AND (v.field_adpersonfamilyname_value LIKE '%' ESCAPE '\\') AND (v.field_adpersondateofborn_value LIKE '%' ESCAPE '\\') AND (v.field_adpersondateofdied_value LIKE '%' ESCAPE '\\') 
ORDER BY v.field_adpersonfamilyname_value ASC, v.field_adpersondateofdied_value DESC
LIMIT 20 OFFSET 0

私のデータベース構成:

max_connections = 300
connect_timeout = 100
max_user_connections = 300
key_buffer = 256M
query_cache_size = 96MB
query_cache_limit = 4MB
table_cache = 1800
table_definition_cache = 1800
sort_buffer_size = 32M
myisam_sort_buffer_size = 32M
tmp_table_size = 64MB
join_buffer_size = 4M
wait_timeout = 60
innodb_buffer_pool_size = 2G
innodb_log_file_size = 1G
max_heap_table_size = 128M
tmp_table_size = 128M
max_allowed_packet = 32M
thread_cache_size = 128

mysqlサーバーサイトを起動すると検索は高速ですが、数時間後に「tmpテーブルへのコピー」がデータのコピーを開始し、サーバーが遅くなり、最終的にクラッシュします。システムには 8GB の RAM とそのデュアルコアがあります。

助けてください!

4

1 に答える 1

0

この特定のケースでは、最初に選択したい行の ID を検索してから、他のテーブルを追加する方が速いと思います。少し遊んでください。

select <fields>
from node n
<joins>
where nid in 
  ( select nid 
    from node 
    where n.status = 1 
      and n.type = 'advertisement
  )

特に別のテーブルの 1 つのフィールドだけが必要な場合の別の解決策は、サブセレクトを使用することです。これは遅く聞こえますが、結合よりも高速な場合があります。

select n.fields,
  (select field_adpersonid_value from field_data_field_adpersonid i ON i.entity_id = n.nid) as field_adpersonid_value
from node n
where .. etc

また、Explain を試して、どこが遅いかを確認することもできます。

于 2013-10-10T13:03:19.107 に答える