YugabyteDB automatically splits YCQL user tables into multiple shards, called tablets, using a hash based strategy.
You can see the tablets for a table via the admin UI for YB-Master, which is available at http://<<YB-Master IP>>:7000.
We can scrape the information provided from the admin UI and get the details for a particular table.
I’ve encapsulated the logic in a shell script.
#!/bin/bash
shopt -s expand_aliases
# Script: list_tablets_ycql.sh
# Description: This script will list tablet details for a given YCQL table by scraping data from
# the YB Master Admin UI.
# Created: 12/01/2022
# Last update: 12/04/2022
# Edits:
# 12/03/2022 Added a connection an request timeout of 3600 seconds to YCQL calls
# 12/04/2022 Added a check if ycqlsh access is set up properly
# 12/04/2022 Set CONSISTENCY ONE for ycql sessions running COUNTs to enable follower reads
# 12/04/2022 Fixed Raft Config output to include all nodes
# Call Spec:
# ./list_tablets_ycql.sh <> <> <> <> <>
# The password parameter is optional. If ommitted, the user will be prompted for a password for each YCQL call.
# Example Use:
# ./list_tablets_ycql.sh test test 172.152.101.162 cassandra password
# Reference: https://docs.yugabyte.com/preview/reference/configuration/yb-master/#admin-ui
# Defaults
YCQL_TIMEOUT=600
# Verify input parameters
# Check if table keyspace name was provided
if [ -z "$1" ]
then
echo "Please provide a keyspace name"
exit 0
else
YB_KEYSPACE=$1
fi
# Check if table name was provided
if [ -z "$2" ]
then
echo "Please provide a table name"
exit 0
else
YB_TABLE_NAME=$2
fi
# Check if IP or hostname was provided
if [ -z "$3" ]
then
echo "Please provide an IP or hostname for a YB Master node"
exit 0
else
YB_IP=$3
fi
# Check if database user name was provided
if [ -z "$4" ]
then
echo "Please provide a database username"
exit 0
else
YB_USER=$4
fi
# Set up the YCQLSH alias below per your environment
YB_PATH='/home/yugabyte/yb-software/yugabyte-2.17.1.1186-b4-centos-x86_64/bin/ycqlsh'
# Check if ycqlsh access is set up properly
if ! command -v $YB_PATH &> /dev/null
then
echo "ycqlsh could not be found"
exit
fi
# If database password was provided, use it in building ycqlsh alias and variable
if [ -z "$5" ]
then
alias y="$YB_PATH $YB_IP -u $YB_USER --connect-timeout=$YCQL_TIMEOUT"
y1="$YB_PATH $YB_IP -u $YB_USER --connect-timeout=$YCQL_TIMEOUT"
else
alias y="$YB_PATH $YB_IP -u $YB_USER -p $5 --connect-timeout=$YCQL_TIMEOUT --request-timeout=$YCQL_TIMEOUT"
y1="$YB_PATH $YB_IP -u $YB_USER -p $5 --connect-timeout=$YCQL_TIMEOUT --request-timeout=$YCQL_TIMEOUT"
fi
# Check if table exists
tc=`y -e "SELECT COUNT(*) FROM system_schema.tables WHERE keyspace_name = '$YB_KEYSPACE' AND table_name = '$YB_TABLE_NAME';" | awk 'FNR==4{print $1}'`
if [ $tc -gt 0 ]
then
# Get the PK HASH columns for the table.
table_id=`curl -s http://$YB_IP:7000/tables | sed -e 's/<[^>]*>/|/g' | awk -F\| -v YB_KEYSPACE=$YB_KEYSPACE -v YB_TABLE_NAME=$YB_TABLE_NAME '{if ($3==YB_KEYSPACE && $6==YB_TABLE_NAME && $15=="") print $13}'`
pk=`curl -s http://$YB_IP:7000/table?id=$table_id | grep "NOT NULL PARTITION KEY" | sed -e 's/<[^>]*>/|/g' | awk -F\| '{print $3}' | paste -d ',' -s`
if [ -z "$pk" ]
then
echo "The table \"$1.$2\" does not have a HASH sharded primary key defined."
exit 1
fi
# Get the number of nodes in the cluster
nc=`y -e "SELECT COUNT(*) FROM system.peers;" | awk 'FNR==4{print $1}'`
nc=$((nc+1))
# Scrap the YB Master UI for Tablet data and print to it to the screen
curl -s http://$YB_IP:9000/tablets | grep -A $nc $table_id | sed -e 's/<[^>]*>/|/g' | sed 's/\([|]\)\1\+/\1/g' | sed 's:^.\(.*\).$:\1:' | sed -z 's/\n|LEADER:/|LEADER:/g' | sed -z 's/\n|FOLLOWER:/ FOLLOWER:/g' | sed '/^$/d' | awk -F\| -v pk="$pk" -v y1="$y1" -v k="$YB_KEYSPACE" -v tn="$YB_TABLE_NAME" 'BEGIN{print "Tablet ID|Partition|State|Hidden|Row Count|Num SST Files|On-disk size|RaftConfig"}; {p=index($5,","); cmd=y1" -e \"CONSISTENCY ONE; SELECT COUNT("pk") FROM "k"."tn" WHERE partition_hash("pk") >= \""strtonum( "0x" substr($5, p-4, 4))"\" AND partition_hash("pk") <= \""strtonum( "0x" substr($5, p+4, 4))"\";\" | sed -n 5p"; cmd | getline rc; close(cmd); print $4"|"$5"|"$6"|"$7"|"strtonum(rc)"|"$8"|"$9" / "$10" / "$11" / "$12" / "$13"|"$14;}' | column -t -s"|"
else
echo "The table \"$1.$2\" does not exist."
fi
exit 0
Example:
[yugabyte@ip-172-152-101-162 ~]$ alias c
alias c='ycqlsh 172.152.101.162 -u cassandra -p Yugabyte123! --connect-timeout=3600 --request-timeout=3600 -r'
[yugabyte@ip-172-152-101-162 ~]$ time c -e "SELECT COUNT(*) FROM test.test;"
count
----------
10000000
(1 rows)
real 0m12.829s
user 0m0.183s
sys 0m0.028s
[yugabyte@ip-172-152-101-162 ~]$ time ./list_tablets_ycql.sh test test 172.152.101.162 cassandra Yugabyte123!
Tablet ID Partition State Hidden Row Count Num SST Files On-disk size RaftConfig
2e37ea5013cc4b4bab0107d3950f762d hash_split: [0x0000, 0x5554] RUNNING false 3334342 4 Total: 194.85M / Consensus Metadata: 1.5K / WAL Files: 128.00M / SST Files: 66.85M / SST Files Uncompressed: 174.19M LEADER: 172.152.101.162 FOLLOWER: 172.161.52.255 FOLLOWER: 172.150.43.0
54f9402a2a1c4001ae47d553086c4425 hash_split: [0x5555, 0xAAA9] RUNNING false 3334859 4 Total: 194.87M / Consensus Metadata: 1.5K / WAL Files: 128.00M / SST Files: 66.87M / SST Files Uncompressed: 174.22M LEADER: 172.152.101.162 FOLLOWER: 172.161.52.255 FOLLOWER: 172.150.43.0
b5dc1b9693ef4914932e986e50d29528 hash_split: [0xAAAA, 0xFFFF] RUNNING false 3330799 4 Total: 194.86M / Consensus Metadata: 1.5K / WAL Files: 128.00M / SST Files: 66.85M / SST Files Uncompressed: 174.17M LEADER: 172.152.101.162 FOLLOWER: 172.161.52.255 FOLLOWER: 172.150.43.0
real 0m15.514s
user 0m0.868s
sys 0m0.158s
Have Fun!