Share via


PostgreSQL için Azure Cosmos DB'de yararlı tanılama sorguları

ŞUNLAR IÇIN GEÇERLIDIR: PostgreSQL için Azure Cosmos DB (PostgreSQL'e citus veritabanı uzantısıyla desteklenir)

Belirli bir kiracı için hangi düğümün veri içerdiğini bulma

Çok kiracılı kullanım örneğinde, belirli bir kiracının satırlarını içeren çalışan düğümünü belirleyebiliriz. PostgreSQL için Azure Cosmos DB, dağıtılmış tablo satırlarını parçalar halinde gruplandırır ve her bir parçanın kümedeki bir çalışan düğümüne yerleştirir.

Uygulamamızın kiracılarının depo olduğunu ve mağaza kimliği=4 için hangi çalışan düğümünü barındırdığı bulmak istediğimizi varsayalım. Başka bir deyişle, dağıtım sütunu 4 değerine sahip satırları içeren parçanın yerleşimini bulmak istiyoruz:

SELECT shardid, shardstate, shardlength, nodename, nodeport, placementid
  FROM pg_dist_placement AS placement,
       pg_dist_node AS node
 WHERE placement.groupid = node.groupid
   AND node.noderole = 'primary'
   AND shardid = (
     SELECT get_shard_id_for_distribution_column('stores', 4)
   );

Çıkış, çalışan veritabanının ana bilgisayarını ve bağlantı noktasını içerir.

┌─────────┬────────────┬─────────────┬───────────┬──────────┬─────────────┐
│ shardid │ shardstate │ shardlength │ nodename  │ nodeport │ placementid │
├─────────┼────────────┼─────────────┼───────────┼──────────┼─────────────┤
│  102009 │          1 │           0 │ 10.0.0.16 │     5432 │           2 │
└─────────┴────────────┴─────────────┴───────────┴──────────┴─────────────┘

Dağıtılmış şemayı barındıran düğümü bulma

Dağıtılmış şemalar, bu şemalarda oluşturulan tabloların parça anahtarı olmadan birlikte konumlandırılmış dağıtılmış tablolara dönüştürülmesi gibi tek tek ortak konum gruplarıyla otomatik olarak ilişkilendirilir. ile citus_schemasbirleştirerek citus_shards dağıtılmış şemanın nerede olduğunu bulabilirsiniz:

select schema_name, nodename, nodeport
  from citus_shards
  join citus_schemas cs
    on cs.colocation_id = citus_shards.colocation_id
 group by 1,2,3;
 schema_name | nodename  | nodeport
-------------+-----------+----------
 a           | localhost |     9701
 b           | localhost |     9702
 with_data   | localhost |     9702

Ayrıca, tüm tablolar için ayrıntılı bir döküme sahip olmak için doğrudan şema tablo türüne filtrelemeyi sorgulayabilirsiniz citus_shards .

select * from citus_shards where citus_table_type = 'schema';
   table_name   | shardid |      shard_name       | citus_table_type | colocation_id | nodename  | nodeport | shard_size | schema_name | colocation_id | schema_size | schema_owner
----------------+---------+-----------------------+------------------+---------------+-----------+----------+------------+-------------+---------------+-------------+--------------
 a.cities       |  102080 | a.cities_102080       | schema           |             4 | localhost |     9701 |       8192 | a           |             4 | 128 kB      | citus
 a.map_tags     |  102145 | a.map_tags_102145     | schema           |             4 | localhost |     9701 |      32768 | a           |             4 | 128 kB      | citus
 a.measurement  |  102047 | a.measurement_102047  | schema           |             4 | localhost |     9701 |          0 | a           |             4 | 128 kB      | citus
 a.my_table     |  102179 | a.my_table_102179     | schema           |             4 | localhost |     9701 |      16384 | a           |             4 | 128 kB      | citus
 a.people       |  102013 | a.people_102013       | schema           |             4 | localhost |     9701 |      32768 | a           |             4 | 128 kB      | citus
 a.test         |  102008 | a.test_102008         | schema           |             4 | localhost |     9701 |       8192 | a           |             4 | 128 kB      | citus
 a.widgets      |  102146 | a.widgets_102146      | schema           |             4 | localhost |     9701 |      32768 | a           |             4 | 128 kB      | citus
 b.test         |  102009 | b.test_102009         | schema           |             5 | localhost |     9702 |       8192 | b           |             5 | 32 kB       | citus
 b.test_col     |  102012 | b.test_col_102012     | schema           |             5 | localhost |     9702 |      24576 | b           |             5 | 32 kB       | citus
 with_data.test |  102180 | with_data.test_102180 | schema           |            11 | localhost |     9702 |     647168 | with_data   |            11 | 632 kB      | citus

Tablonun dağıtım sütununu bulma

Her dağıtılmış tablonun bir "dağıtım sütunu" vardır. (Daha fazla bilgi için bkz. Dağıtılmış Veri Modelleme.) Hangi sütun olduğunu bilmek önemli olabilir. Örneğin, tabloları eklerken veya filtrelerken "dağıtım sütununa filtre ekle" gibi ipuçları içeren hata iletileri görebilirsiniz.

pg_dist_* Koordinatör düğümündeki tablolar, dağıtılmış veritabanı hakkında çeşitli meta veriler içerir. Özellikle pg_dist_partition her tablonun dağıtım sütunu hakkındaki bilgileri tutar. Meta verilerdeki alt düzey ayrıntılardan dağıtım sütununun adını aramak için kullanışlı bir yardımcı program işlevi kullanabilirsiniz. Bir örnek ve çıktısı aşağıda verilmiştir:

-- create example table

CREATE TABLE products (
  store_id bigint,
  product_id bigint,
  name text,
  price money,

  CONSTRAINT products_pkey PRIMARY KEY (store_id, product_id)
);

-- pick store_id as distribution column

SELECT create_distributed_table('products', 'store_id');

-- get distribution column name for products table

SELECT column_to_column_name(logicalrelid, partkey) AS dist_col_name
  FROM pg_dist_partition
 WHERE logicalrelid='products'::regclass;

Örnek çıkış:

┌───────────────┐
│ dist_col_name │
├───────────────┤
│ store_id      │
└───────────────┘

Kilitleri algılama

Bu sorgu tüm çalışan düğümlerinde çalıştırılır ve kilitleri, ne kadar süre açık olduklarını ve sorunlu sorguları tanımlar:

SELECT run_command_on_workers($cmd$
  SELECT array_agg(
    blocked_statement || ' $ ' || cur_stmt_blocking_proc
    || ' $ ' || cnt::text || ' $ ' || age
  )
  FROM (
    SELECT blocked_activity.query    AS blocked_statement,
           blocking_activity.query   AS cur_stmt_blocking_proc,
           count(*)                  AS cnt,
           age(now(), min(blocked_activity.query_start)) AS "age"
    FROM pg_catalog.pg_locks         blocked_locks
    JOIN pg_catalog.pg_stat_activity blocked_activity
      ON blocked_activity.pid = blocked_locks.pid
    JOIN pg_catalog.pg_locks         blocking_locks
      ON blocking_locks.locktype = blocked_locks.locktype
     AND blocking_locks.DATABASE IS NOT DISTINCT FROM blocked_locks.DATABASE
     AND blocking_locks.relation IS NOT DISTINCT FROM blocked_locks.relation
     AND blocking_locks.page IS NOT DISTINCT FROM blocked_locks.page
     AND blocking_locks.tuple IS NOT DISTINCT FROM blocked_locks.tuple
     AND blocking_locks.virtualxid IS NOT DISTINCT FROM blocked_locks.virtualxid
     AND blocking_locks.transactionid IS NOT DISTINCT FROM blocked_locks.transactionid
     AND blocking_locks.classid IS NOT DISTINCT FROM blocked_locks.classid
     AND blocking_locks.objid IS NOT DISTINCT FROM blocked_locks.objid
     AND blocking_locks.objsubid IS NOT DISTINCT FROM blocked_locks.objsubid
     AND blocking_locks.pid != blocked_locks.pid
    JOIN pg_catalog.pg_stat_activity blocking_activity ON blocking_activity.pid = blocking_locks.pid
    WHERE NOT blocked_locks.GRANTED
     AND blocking_locks.GRANTED
    GROUP BY blocked_activity.query,
             blocking_activity.query
    ORDER BY 4
  ) a
$cmd$);

Örnek çıkış:

┌───────────────────────────────────────────────────────────────────────────────────┐
│                               run_command_on_workers                              │
├───────────────────────────────────────────────────────────────────────────────────┤
│ (10.0.0.16,5432,t,"")                                                             │
│ (10.0.0.20,5432,t,"{""update ads_102277 set name = 'new name' where id = 1; $ sel…│
│…ect * from ads_102277 where id = 1 for update; $ 1 $ 00:00:03.729519""}")         │
└───────────────────────────────────────────────────────────────────────────────────┘

Parçalarınızın boyutunu sorgulama

Bu sorgu, belirli bir dağıtılmış tablonun adlı my_distributed_tableher parçasının boyutunu sağlar:

SELECT *
FROM run_command_on_shards('my_distributed_table', $cmd$
  SELECT json_build_object(
    'shard_name', '%1$s',
    'size',       pg_size_pretty(pg_table_size('%1$s'))
  );
$cmd$);

Örnek çıkış:

┌─────────┬─────────┬───────────────────────────────────────────────────────────────────────┐
│ shardid │ success │                                result                                 │
├─────────┼─────────┼───────────────────────────────────────────────────────────────────────┤
│  102008 │ t       │ {"shard_name" : "my_distributed_table_102008", "size" : "2416 kB"}    │
│  102009 │ t       │ {"shard_name" : "my_distributed_table_102009", "size" : "3960 kB"}    │
│  102010 │ t       │ {"shard_name" : "my_distributed_table_102010", "size" : "1624 kB"}    │
│  102011 │ t       │ {"shard_name" : "my_distributed_table_102011", "size" : "4792 kB"}    │
└─────────┴─────────┴───────────────────────────────────────────────────────────────────────┘

Tüm dağıtılmış tabloların boyutunu sorgulama

Bu sorgu, dağıtılmış her tablonun boyutlarının listesini ve dizinlerinin boyutunu alır.

SELECT
  tablename,
  pg_size_pretty(
    citus_total_relation_size(tablename::text)
  ) AS total_size
FROM pg_tables pt
JOIN pg_dist_partition pp
  ON pt.tablename = pp.logicalrelid::text
WHERE schemaname = 'public';

Örnek çıkış:

┌───────────────┬────────────┐
│   tablename   │ total_size │
├───────────────┼────────────┤
│ github_users  │ 39 MB      │
│ github_events │ 98 MB      │
└───────────────┴────────────┘

Dağıtılmış tablo boyutunu sorgulamaya yönelik başka PostgreSQL için Azure Cosmos DB işlevleri olduğunu unutmayın. Bkz . Tablo boyutunu belirleme.

Kullanılmayan dizinleri tanımlama

Aşağıdaki sorgu, belirli bir dağıtılmış tablo için çalışan düğümlerinde kullanılmayan dizinleri belirler (my_distributed_table)

SELECT *
FROM run_command_on_shards('my_distributed_table', $cmd$
  SELECT array_agg(a) as infos
  FROM (
    SELECT (
      schemaname || '.' || relname || '##' || indexrelname || '##'
                 || pg_size_pretty(pg_relation_size(i.indexrelid))::text
                 || '##' || idx_scan::text
    ) AS a
    FROM  pg_stat_user_indexes ui
    JOIN  pg_index i
    ON    ui.indexrelid = i.indexrelid
    WHERE NOT indisunique
    AND   idx_scan < 50
    AND   pg_relation_size(relid) > 5 * 8192
    AND   (schemaname || '.' || relname)::regclass = '%s'::regclass
    ORDER BY
      pg_relation_size(i.indexrelid) / NULLIF(idx_scan, 0) DESC nulls first,
      pg_relation_size(i.indexrelid) DESC
  ) sub
$cmd$);

Örnek çıkış:

┌─────────┬─────────┬───────────────────────────────────────────────────────────────────────┐
│ shardid │ success │                            result                                     │
├─────────┼─────────┼───────────────────────────────────────────────────────────────────────┤
│  102008 │ t       │                                                                       │
│  102009 │ t       │ {"public.my_distributed_table_102009##some_index_102009##28 MB##0"}   │
│  102010 │ t       │                                                                       │
│  102011 │ t       │                                                                       │
└─────────┴─────────┴───────────────────────────────────────────────────────────────────────┘

İstemci bağlantı sayısını izleme

Aşağıdaki sorgu, koordinatörde açık olan bağlantıları sayar ve türe göre gruplandırar.

SELECT state, count(*)
FROM pg_stat_activity
GROUP BY state;

Örnek çıkış:

┌────────┬───────┐
│ state  │ count │
├────────┼───────┤
│ active │     3 │
│ idle   │     3 │
│ ∅      │     6 │
└────────┴───────┘

Sistem sorgularını görüntüleme

Etkin sorgular

Görünümde pg_stat_activity şu anda hangi sorguların yürütülmekte olduğu gösterilir. Etkin olarak yürütülenleri ve arka uçlarının işlem kimliğini bulmak için filtre uygulayabilirsiniz:

SELECT pid, query, state
  FROM pg_stat_activity
 WHERE state != 'idle';

Sorgular neden bekliyor?

Ayrıca bekleyen boşta olmayan sorguların en yaygın nedenlerini görmek için sorgulayabiliriz. Nedenlerle ilgili bir açıklama için PostgreSQL belgelerine bakın.

SELECT wait_event || ':' || wait_event_type AS type, count(*) AS number_of_occurences
  FROM pg_stat_activity
 WHERE state != 'idle'
GROUP BY wait_event, wait_event_type
ORDER BY number_of_occurences DESC;

Ayrı bir sorguda eşzamanlı olarak çalıştırılırken pg_sleep örnek çıktı:

┌─────────────────┬──────────────────────┐
│      type       │ number_of_occurences │
├─────────────────┼──────────────────────┤
│ ∅               │                    1 │
│ PgSleep:Timeout │                    1 │
└─────────────────┴──────────────────────┘

Dizin isabet oranı

Bu sorgu, tüm düğümler arasında dizin isabet oranınızı sağlar. Dizin isabet oranı, dizinlerin sorgulanırken ne sıklıkta kullanıldığını belirlemede yararlıdır. %95 veya üzeri bir değer idealdir.

-- on coordinator
SELECT 100 * (sum(idx_blks_hit) - sum(idx_blks_read)) / sum(idx_blks_hit) AS index_hit_rate
  FROM pg_statio_user_indexes;

-- on workers
SELECT nodename, result as index_hit_rate
FROM run_command_on_workers($cmd$
  SELECT 100 * (sum(idx_blks_hit) - sum(idx_blks_read)) / sum(idx_blks_hit) AS index_hit_rate
    FROM pg_statio_user_indexes;
$cmd$);

Örnek çıkış:

┌───────────┬────────────────┐
│ nodename  │ index_hit_rate │
├───────────┼────────────────┤
│ 10.0.0.16 │ 96.0           │
│ 10.0.0.20 │ 98.0           │
└───────────┴────────────────┘

Önbellek isabet oranı

Çoğu uygulama genellikle toplam verilerinin küçük bir kısmına aynı anda erişir. PostgreSQL, diskten yavaş okumaları önlemek için sık erişilen verileri bellekte tutar. bununla ilgili istatistikleri pg_statio_user_tables görünümünde görebilirsiniz.

Önemli bir ölçüm, iş yükünüzdeki diske göre bellek önbelleğinden gelen veri yüzdesidir:

-- on coordinator
SELECT
  sum(heap_blks_read) AS heap_read,
  sum(heap_blks_hit)  AS heap_hit,
  100 * sum(heap_blks_hit) / (sum(heap_blks_hit) + sum(heap_blks_read)) AS cache_hit_rate
FROM
  pg_statio_user_tables;

-- on workers
SELECT nodename, result as cache_hit_rate
FROM run_command_on_workers($cmd$
  SELECT
    100 * sum(heap_blks_hit) / (sum(heap_blks_hit) + sum(heap_blks_read)) AS cache_hit_rate
  FROM
    pg_statio_user_tables;
$cmd$);

Örnek çıkış:

┌───────────┬──────────┬─────────────────────┐
│ heap_read │ heap_hit │   cache_hit_rate    │
├───────────┼──────────┼─────────────────────┤
│         1 │      132 │ 99.2481203007518796 │
└───────────┴──────────┴─────────────────────┘

Kendinizi %99'un çok daha düşük bir oranıyla bulursanız veritabanınızda kullanılabilen önbelleği artırmayı düşünebilirsiniz.

Sonraki adımlar