├── .gitignore ├── README.md ├── assets ├── mv1_plan.png ├── mv2_plan.png └── project.png ├── clickhouse-sql ├── avg_fare_amt.sql └── demo_table.sql ├── commands.sh ├── data ├── taxi_zone.csv └── yellow_tripdata_2022-01.parquet ├── docker ├── Dockerfile ├── Dockerfile.hdfs ├── README.md ├── aws.env ├── aws │ ├── .gitignore │ ├── Dockerfile │ └── aws-build.sh ├── dashboards │ ├── risingwave-dev-dashboard.json │ └── risingwave-user-dashboard.json ├── docker-compose.yml ├── grafana-risedev-dashboard.yml ├── grafana-risedev-datasource.yml ├── grafana.ini ├── hdfs_env.sh ├── multiple_object_storage.env ├── prometheus.yaml └── risingwave.toml ├── homework.md ├── index.html ├── requirements.txt ├── risingwave-sql ├── sink │ ├── avg_fare_amt_sink.sql │ └── demo_clickhouse_sink.sql └── table │ ├── taxi_zone.sql │ └── trip_data.sql ├── seed_kafka.py ├── server.py ├── slides.pdf └── workshop.md /.gitignore: -------------------------------------------------------------------------------- 1 | activate/ 2 | .venv/ 3 | dashboards/ 4 | grafana* 5 | prometheus* 6 | risingwave.toml 7 | homework/ 8 | .DS_Store 9 | slides.key 10 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | 5 | 6 |

7 | 8 | 9 | 10 | 11 |

12 | Documentation   📑    16 | Hands-on Tutorials   🎯    20 | RisingWave Cloud   🚀    24 | 28 | Get Instant Help 29 | 30 |

31 |
32 | 36 | Slack 37 | 38 | 42 | X 43 | 44 | 48 | YouTube 49 | 50 |
51 | 52 | ## Stream processing in SQL with RisingWave 53 | 54 | In this hands-on workshop, we’ll learn how to process real-time streaming data using SQL in RisingWave. The system we’ll use is [RisingWave](https://github.com/risingwavelabs/risingwave), an open-source SQL database for processing and managing streaming data. You may not feel unfamiliar with RisingWave’s user experience, as it’s fully wire compatible with PostgreSQL. 55 | 56 | ![RisingWave](https://raw.githubusercontent.com/risingwavelabs/risingwave-docs/main/docs/images/new_archi_grey.png) 57 | 58 | We will use the NYC Taxi dataset, which contains information 59 | about taxi trips in New York City. 60 | 61 | We’ll cover the following topics in this Workshop: 62 | 63 | - Why Stream Processing? 64 | - Stateless computation (Filters, Projections) 65 | - Stateful Computation (Aggregations, Joins) 66 | - Data Ingestion and Delivery 67 | 68 | RisingWave in 10 Minutes: 69 | https://tutorials.risingwave.com/docs/intro 70 | 71 | ## Prerequisites 72 | 73 | 1. Docker and Docker Compose 74 | 2. Python 3.7 or later 75 | 3. `pip` and `virtualenv` for Python 76 | 4. `psql` (I use PostgreSQL-14.9) 77 | 5. Clone this repository: 78 | ```sh 79 | git clone git@github.com:risingwavelabs/risingwave-data-talks-workshop-2024-03-04.git 80 | cd risingwave-data-talks-workshop-2024-03-04 81 | ``` 82 | Or, if you prefer HTTPS: 83 | ```sh 84 | git clone https://github.com/risingwavelabs/risingwave-data-talks-workshop-2024-03-04.git 85 | cd risingwave-data-talks-workshop-2024-03-04 86 | ``` 87 | 88 | ## Note on the dataset 89 | 90 | The NYC Taxi dataset is a public dataset that contains information about taxi trips in New York City. 91 | The dataset is available in Parquet format and can be downloaded from the [NYC Taxi & Limousine Commission website](https://www1.nyc.gov/site/tlc/about/tlc-trip-record-data.page). 92 | 93 | We will be using the following files from the dataset: 94 | - `yellow_tripdata_2022-01.parquet` 95 | - `taxi_zone.csv` 96 | 97 | For your convenience, these have already been downloaded and are available in the `data` directory. 98 | 99 | The file `seed_kafka.py` contains the logic to process the data and populate RisingWave. 100 | 101 | In this workshop, we will replace the `timestamp` fields in the `trip_data` with `timestamp`s close to the current time. 102 | That's because `yellow_tripdata_2022-01.parquet` contains historical data from 2022, 103 | and we want to simulate processing real-time data. 104 | 105 | ## Project Structure 106 | 107 | ```plaintext 108 | $ tree -L 1 109 | . 110 | ├── README.md # This file 111 | ├── clickhouse-sql # SQL scripts for Clickhouse 112 | ├── commands.sh # Commands to operate the cluster 113 | ├── data # Data files (trip_data, taxi_zone) 114 | ├── docker # Contains docker compose files 115 | ├── requirements.txt # Python dependencies 116 | ├── risingwave-sql # SQL scripts for RisingWave (includes some homework files) 117 | └── seed_kafka.py # Python script to seed Kafka 118 | ``` 119 | 120 | ## Getting Started 121 | 122 | Before getting your hands dirty with the project, we will: 123 | 1. Run some diagnostics. 124 | 2. Start the RisingWave cluster. 125 | 3. Setup our python environment. 126 | 127 | ```bash 128 | # Check version of psql 129 | psql --version 130 | source commands.sh 131 | 132 | # Start the RW cluster 133 | start-cluster 134 | 135 | # Setup python 136 | python3 -m venv .venv 137 | source .venv/bin/activate 138 | pip install -r requirements.txt 139 | ``` 140 | 141 | `commands.sh` contains several commands to operate the cluster. You may reference it to see what commands are available. 142 | 143 | Now you're ready to start on the [workshop](./workshop.md)! -------------------------------------------------------------------------------- /assets/mv1_plan.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/risingwavelabs/risingwave-data-talks-workshop-2024-03-04/c35d3d9de58f174853b5f29439241c966d88964f/assets/mv1_plan.png -------------------------------------------------------------------------------- /assets/mv2_plan.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/risingwavelabs/risingwave-data-talks-workshop-2024-03-04/c35d3d9de58f174853b5f29439241c966d88964f/assets/mv2_plan.png -------------------------------------------------------------------------------- /assets/project.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/risingwavelabs/risingwave-data-talks-workshop-2024-03-04/c35d3d9de58f174853b5f29439241c966d88964f/assets/project.png -------------------------------------------------------------------------------- /clickhouse-sql/avg_fare_amt.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE avg_fare_amt( 2 | avg_fare_amount_per_hour numeric, 3 | num_rides_per_hour Int64, 4 | ) ENGINE = ReplacingMergeTree 5 | PRIMARY KEY (avg_fare_amount_per_hour, num_rides_per_hour); -------------------------------------------------------------------------------- /clickhouse-sql/demo_table.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE demo_test( 2 | seq_id Int32, 3 | user_id Int32, 4 | user_name String, 5 | ) ENGINE = ReplacingMergeTree 6 | PRIMARY KEY (seq_id); -------------------------------------------------------------------------------- /commands.sh: -------------------------------------------------------------------------------- 1 | export PGHOST=localhost 2 | export PGPORT=4566 3 | export PGUSER=root 4 | export PGDATABASE=dev 5 | 6 | # Seed trip data from the parquet file 7 | seed-kafka() { 8 | ./seed_kafka.py 9 | } 10 | 11 | # Seed trip data from the parquet file 12 | stream-kafka() { 13 | ./seed_kafka.py update 14 | } 15 | 16 | # TODO: Command to create ALL ddls. 17 | # TODO: Command + script to send kafka updates. 18 | 19 | # Starts the risingwave cluster 20 | start-cluster() { 21 | docker-compose -f docker/docker-compose.yml up -d 22 | } 23 | 24 | # Stops the risingwave cluster 25 | stop-cluster() { 26 | docker-compose -f docker/docker-compose.yml down 27 | } 28 | 29 | # Cleans the risingwave cluster 30 | clean-cluster() { 31 | docker-compose -f docker/docker-compose.yml down -v 32 | } 33 | 34 | # Starts the clickhouse client. 35 | # You can run files like: 36 | # clickhouse-client < file.sql 37 | clickhouse-client() { 38 | docker exec -i clickhouse clickhouse-client 39 | } 40 | 41 | # Starts an interactive clickhouse session. 42 | clickhouse-client-term() { 43 | docker exec -it clickhouse clickhouse-client 44 | } -------------------------------------------------------------------------------- /data/taxi_zone.csv: -------------------------------------------------------------------------------- 1 | LocationID,Borough,Zone,service_zone 2 | 1,EWR,Newark Airport,EWR 3 | 2,Queens,Jamaica Bay,Boro Zone 4 | 3,Bronx,Allerton/Pelham Gardens,Boro Zone 5 | 4,Manhattan,Alphabet City,Yellow Zone 6 | 5,Staten Island,Arden Heights,Boro Zone 7 | 6,Staten Island,Arrochar/Fort Wadsworth,Boro Zone 8 | 7,Queens,Astoria,Boro Zone 9 | 8,Queens,Astoria Park,Boro Zone 10 | 9,Queens,Auburndale,Boro Zone 11 | 10,Queens,Baisley Park,Boro Zone 12 | 11,Brooklyn,Bath Beach,Boro Zone 13 | 12,Manhattan,Battery Park,Yellow Zone 14 | 13,Manhattan,Battery Park City,Yellow Zone 15 | 14,Brooklyn,Bay Ridge,Boro Zone 16 | 15,Queens,Bay Terrace/Fort Totten,Boro Zone 17 | 16,Queens,Bayside,Boro Zone 18 | 17,Brooklyn,Bedford,Boro Zone 19 | 18,Bronx,Bedford Park,Boro Zone 20 | 19,Queens,Bellerose,Boro Zone 21 | 20,Bronx,Belmont,Boro Zone 22 | 21,Brooklyn,Bensonhurst East,Boro Zone 23 | 22,Brooklyn,Bensonhurst West,Boro Zone 24 | 23,Staten Island,Bloomfield/Emerson Hill,Boro Zone 25 | 24,Manhattan,Bloomingdale,Yellow Zone 26 | 25,Brooklyn,Boerum Hill,Boro Zone 27 | 26,Brooklyn,Borough Park,Boro Zone 28 | 27,Queens,Breezy Point/Fort Tilden/Riis Beach,Boro Zone 29 | 28,Queens,Briarwood/Jamaica Hills,Boro Zone 30 | 29,Brooklyn,Brighton Beach,Boro Zone 31 | 30,Queens,Broad Channel,Boro Zone 32 | 31,Bronx,Bronx Park,Boro Zone 33 | 32,Bronx,Bronxdale,Boro Zone 34 | 33,Brooklyn,Brooklyn Heights,Boro Zone 35 | 34,Brooklyn,Brooklyn Navy Yard,Boro Zone 36 | 35,Brooklyn,Brownsville,Boro Zone 37 | 36,Brooklyn,Bushwick North,Boro Zone 38 | 37,Brooklyn,Bushwick South,Boro Zone 39 | 38,Queens,Cambria Heights,Boro Zone 40 | 39,Brooklyn,Canarsie,Boro Zone 41 | 40,Brooklyn,Carroll Gardens,Boro Zone 42 | 41,Manhattan,Central Harlem,Boro Zone 43 | 42,Manhattan,Central Harlem North,Boro Zone 44 | 43,Manhattan,Central Park,Yellow Zone 45 | 44,Staten Island,Charleston/Tottenville,Boro Zone 46 | 45,Manhattan,Chinatown,Yellow Zone 47 | 46,Bronx,City Island,Boro Zone 48 | 47,Bronx,Claremont/Bathgate,Boro Zone 49 | 48,Manhattan,Clinton East,Yellow Zone 50 | 49,Brooklyn,Clinton Hill,Boro Zone 51 | 50,Manhattan,Clinton West,Yellow Zone 52 | 51,Bronx,Co-Op City,Boro Zone 53 | 52,Brooklyn,Cobble Hill,Boro Zone 54 | 53,Queens,College Point,Boro Zone 55 | 54,Brooklyn,Columbia Street,Boro Zone 56 | 55,Brooklyn,Coney Island,Boro Zone 57 | 56,Queens,Corona,Boro Zone 58 | 57,Queens,Corona,Boro Zone 59 | 58,Bronx,Country Club,Boro Zone 60 | 59,Bronx,Crotona Park,Boro Zone 61 | 60,Bronx,Crotona Park East,Boro Zone 62 | 61,Brooklyn,Crown Heights North,Boro Zone 63 | 62,Brooklyn,Crown Heights South,Boro Zone 64 | 63,Brooklyn,Cypress Hills,Boro Zone 65 | 64,Queens,Douglaston,Boro Zone 66 | 65,Brooklyn,Downtown Brooklyn/MetroTech,Boro Zone 67 | 66,Brooklyn,DUMBO/Vinegar Hill,Boro Zone 68 | 67,Brooklyn,Dyker Heights,Boro Zone 69 | 68,Manhattan,East Chelsea,Yellow Zone 70 | 69,Bronx,East Concourse/Concourse Village,Boro Zone 71 | 70,Queens,East Elmhurst,Boro Zone 72 | 71,Brooklyn,East Flatbush/Farragut,Boro Zone 73 | 72,Brooklyn,East Flatbush/Remsen Village,Boro Zone 74 | 73,Queens,East Flushing,Boro Zone 75 | 74,Manhattan,East Harlem North,Boro Zone 76 | 75,Manhattan,East Harlem South,Boro Zone 77 | 76,Brooklyn,East New York,Boro Zone 78 | 77,Brooklyn,East New York/Pennsylvania Avenue,Boro Zone 79 | 78,Bronx,East Tremont,Boro Zone 80 | 79,Manhattan,East Village,Yellow Zone 81 | 80,Brooklyn,East Williamsburg,Boro Zone 82 | 81,Bronx,Eastchester,Boro Zone 83 | 82,Queens,Elmhurst,Boro Zone 84 | 83,Queens,Elmhurst/Maspeth,Boro Zone 85 | 84,Staten Island,Eltingville/Annadale/Prince's Bay,Boro Zone 86 | 85,Brooklyn,Erasmus,Boro Zone 87 | 86,Queens,Far Rockaway,Boro Zone 88 | 87,Manhattan,Financial District North,Yellow Zone 89 | 88,Manhattan,Financial District South,Yellow Zone 90 | 89,Brooklyn,Flatbush/Ditmas Park,Boro Zone 91 | 90,Manhattan,Flatiron,Yellow Zone 92 | 91,Brooklyn,Flatlands,Boro Zone 93 | 92,Queens,Flushing,Boro Zone 94 | 93,Queens,Flushing Meadows-Corona Park,Boro Zone 95 | 94,Bronx,Fordham South,Boro Zone 96 | 95,Queens,Forest Hills,Boro Zone 97 | 96,Queens,Forest Park/Highland Park,Boro Zone 98 | 97,Brooklyn,Fort Greene,Boro Zone 99 | 98,Queens,Fresh Meadows,Boro Zone 100 | 99,Staten Island,Freshkills Park,Boro Zone 101 | 100,Manhattan,Garment District,Yellow Zone 102 | 101,Queens,Glen Oaks,Boro Zone 103 | 102,Queens,Glendale,Boro Zone 104 | 103,Manhattan,Governor's Island/Ellis Island/Liberty Island,Yellow Zone 105 | 104,Manhattan,Governor's Island/Ellis Island/Liberty Island,Yellow Zone 106 | 105,Manhattan,Governor's Island/Ellis Island/Liberty Island,Yellow Zone 107 | 106,Brooklyn,Gowanus,Boro Zone 108 | 107,Manhattan,Gramercy,Yellow Zone 109 | 108,Brooklyn,Gravesend,Boro Zone 110 | 109,Staten Island,Great Kills,Boro Zone 111 | 110,Staten Island,Great Kills Park,Boro Zone 112 | 111,Brooklyn,Green-Wood Cemetery,Boro Zone 113 | 112,Brooklyn,Greenpoint,Boro Zone 114 | 113,Manhattan,Greenwich Village North,Yellow Zone 115 | 114,Manhattan,Greenwich Village South,Yellow Zone 116 | 115,Staten Island,Grymes Hill/Clifton,Boro Zone 117 | 116,Manhattan,Hamilton Heights,Boro Zone 118 | 117,Queens,Hammels/Arverne,Boro Zone 119 | 118,Staten Island,Heartland Village/Todt Hill,Boro Zone 120 | 119,Bronx,Highbridge,Boro Zone 121 | 120,Manhattan,Highbridge Park,Boro Zone 122 | 121,Queens,Hillcrest/Pomonok,Boro Zone 123 | 122,Queens,Hollis,Boro Zone 124 | 123,Brooklyn,Homecrest,Boro Zone 125 | 124,Queens,Howard Beach,Boro Zone 126 | 125,Manhattan,Hudson Sq,Yellow Zone 127 | 126,Bronx,Hunts Point,Boro Zone 128 | 127,Manhattan,Inwood,Boro Zone 129 | 128,Manhattan,Inwood Hill Park,Boro Zone 130 | 129,Queens,Jackson Heights,Boro Zone 131 | 130,Queens,Jamaica,Boro Zone 132 | 131,Queens,Jamaica Estates,Boro Zone 133 | 132,Queens,JFK Airport,Airports 134 | 133,Brooklyn,Kensington,Boro Zone 135 | 134,Queens,Kew Gardens,Boro Zone 136 | 135,Queens,Kew Gardens Hills,Boro Zone 137 | 136,Bronx,Kingsbridge Heights,Boro Zone 138 | 137,Manhattan,Kips Bay,Yellow Zone 139 | 138,Queens,LaGuardia Airport,Airports 140 | 139,Queens,Laurelton,Boro Zone 141 | 140,Manhattan,Lenox Hill East,Yellow Zone 142 | 141,Manhattan,Lenox Hill West,Yellow Zone 143 | 142,Manhattan,Lincoln Square East,Yellow Zone 144 | 143,Manhattan,Lincoln Square West,Yellow Zone 145 | 144,Manhattan,Little Italy/NoLiTa,Yellow Zone 146 | 145,Queens,Long Island City/Hunters Point,Boro Zone 147 | 146,Queens,Long Island City/Queens Plaza,Boro Zone 148 | 147,Bronx,Longwood,Boro Zone 149 | 148,Manhattan,Lower East Side,Yellow Zone 150 | 149,Brooklyn,Madison,Boro Zone 151 | 150,Brooklyn,Manhattan Beach,Boro Zone 152 | 151,Manhattan,Manhattan Valley,Yellow Zone 153 | 152,Manhattan,Manhattanville,Boro Zone 154 | 153,Manhattan,Marble Hill,Boro Zone 155 | 154,Brooklyn,Marine Park/Floyd Bennett Field,Boro Zone 156 | 155,Brooklyn,Marine Park/Mill Basin,Boro Zone 157 | 156,Staten Island,Mariners Harbor,Boro Zone 158 | 157,Queens,Maspeth,Boro Zone 159 | 158,Manhattan,Meatpacking/West Village West,Yellow Zone 160 | 159,Bronx,Melrose South,Boro Zone 161 | 160,Queens,Middle Village,Boro Zone 162 | 161,Manhattan,Midtown Center,Yellow Zone 163 | 162,Manhattan,Midtown East,Yellow Zone 164 | 163,Manhattan,Midtown North,Yellow Zone 165 | 164,Manhattan,Midtown South,Yellow Zone 166 | 165,Brooklyn,Midwood,Boro Zone 167 | 166,Manhattan,Morningside Heights,Boro Zone 168 | 167,Bronx,Morrisania/Melrose,Boro Zone 169 | 168,Bronx,Mott Haven/Port Morris,Boro Zone 170 | 169,Bronx,Mount Hope,Boro Zone 171 | 170,Manhattan,Murray Hill,Yellow Zone 172 | 171,Queens,Murray Hill-Queens,Boro Zone 173 | 172,Staten Island,New Dorp/Midland Beach,Boro Zone 174 | 173,Queens,North Corona,Boro Zone 175 | 174,Bronx,Norwood,Boro Zone 176 | 175,Queens,Oakland Gardens,Boro Zone 177 | 176,Staten Island,Oakwood,Boro Zone 178 | 177,Brooklyn,Ocean Hill,Boro Zone 179 | 178,Brooklyn,Ocean Parkway South,Boro Zone 180 | 179,Queens,Old Astoria,Boro Zone 181 | 180,Queens,Ozone Park,Boro Zone 182 | 181,Brooklyn,Park Slope,Boro Zone 183 | 182,Bronx,Parkchester,Boro Zone 184 | 183,Bronx,Pelham Bay,Boro Zone 185 | 184,Bronx,Pelham Bay Park,Boro Zone 186 | 185,Bronx,Pelham Parkway,Boro Zone 187 | 186,Manhattan,Penn Station/Madison Sq West,Yellow Zone 188 | 187,Staten Island,Port Richmond,Boro Zone 189 | 188,Brooklyn,Prospect-Lefferts Gardens,Boro Zone 190 | 189,Brooklyn,Prospect Heights,Boro Zone 191 | 190,Brooklyn,Prospect Park,Boro Zone 192 | 191,Queens,Queens Village,Boro Zone 193 | 192,Queens,Queensboro Hill,Boro Zone 194 | 193,Queens,Queensbridge/Ravenswood,Boro Zone 195 | 194,Manhattan,Randalls Island,Yellow Zone 196 | 195,Brooklyn,Red Hook,Boro Zone 197 | 196,Queens,Rego Park,Boro Zone 198 | 197,Queens,Richmond Hill,Boro Zone 199 | 198,Queens,Ridgewood,Boro Zone 200 | 199,Bronx,Rikers Island,Boro Zone 201 | 200,Bronx,Riverdale/North Riverdale/Fieldston,Boro Zone 202 | 201,Queens,Rockaway Park,Boro Zone 203 | 202,Manhattan,Roosevelt Island,Boro Zone 204 | 203,Queens,Rosedale,Boro Zone 205 | 204,Staten Island,Rossville/Woodrow,Boro Zone 206 | 205,Queens,Saint Albans,Boro Zone 207 | 206,Staten Island,Saint George/New Brighton,Boro Zone 208 | 207,Queens,Saint Michaels Cemetery/Woodside,Boro Zone 209 | 208,Bronx,Schuylerville/Edgewater Park,Boro Zone 210 | 209,Manhattan,Seaport,Yellow Zone 211 | 210,Brooklyn,Sheepshead Bay,Boro Zone 212 | 211,Manhattan,SoHo,Yellow Zone 213 | 212,Bronx,Soundview/Bruckner,Boro Zone 214 | 213,Bronx,Soundview/Castle Hill,Boro Zone 215 | 214,Staten Island,South Beach/Dongan Hills,Boro Zone 216 | 215,Queens,South Jamaica,Boro Zone 217 | 216,Queens,South Ozone Park,Boro Zone 218 | 217,Brooklyn,South Williamsburg,Boro Zone 219 | 218,Queens,Springfield Gardens North,Boro Zone 220 | 219,Queens,Springfield Gardens South,Boro Zone 221 | 220,Bronx,Spuyten Duyvil/Kingsbridge,Boro Zone 222 | 221,Staten Island,Stapleton,Boro Zone 223 | 222,Brooklyn,Starrett City,Boro Zone 224 | 223,Queens,Steinway,Boro Zone 225 | 224,Manhattan,Stuy Town/Peter Cooper Village,Yellow Zone 226 | 225,Brooklyn,Stuyvesant Heights,Boro Zone 227 | 226,Queens,Sunnyside,Boro Zone 228 | 227,Brooklyn,Sunset Park East,Boro Zone 229 | 228,Brooklyn,Sunset Park West,Boro Zone 230 | 229,Manhattan,Sutton Place/Turtle Bay North,Yellow Zone 231 | 230,Manhattan,Times Sq/Theatre District,Yellow Zone 232 | 231,Manhattan,TriBeCa/Civic Center,Yellow Zone 233 | 232,Manhattan,Two Bridges/Seward Park,Yellow Zone 234 | 233,Manhattan,UN/Turtle Bay South,Yellow Zone 235 | 234,Manhattan,Union Sq,Yellow Zone 236 | 235,Bronx,University Heights/Morris Heights,Boro Zone 237 | 236,Manhattan,Upper East Side North,Yellow Zone 238 | 237,Manhattan,Upper East Side South,Yellow Zone 239 | 238,Manhattan,Upper West Side North,Yellow Zone 240 | 239,Manhattan,Upper West Side South,Yellow Zone 241 | 240,Bronx,Van Cortlandt Park,Boro Zone 242 | 241,Bronx,Van Cortlandt Village,Boro Zone 243 | 242,Bronx,Van Nest/Morris Park,Boro Zone 244 | 243,Manhattan,Washington Heights North,Boro Zone 245 | 244,Manhattan,Washington Heights South,Boro Zone 246 | 245,Staten Island,West Brighton,Boro Zone 247 | 246,Manhattan,West Chelsea/Hudson Yards,Yellow Zone 248 | 247,Bronx,West Concourse,Boro Zone 249 | 248,Bronx,West Farms/Bronx River,Boro Zone 250 | 249,Manhattan,West Village,Yellow Zone 251 | 250,Bronx,Westchester Village/Unionport,Boro Zone 252 | 251,Staten Island,Westerleigh,Boro Zone 253 | 252,Queens,Whitestone,Boro Zone 254 | 253,Queens,Willets Point,Boro Zone 255 | 254,Bronx,Williamsbridge/Olinville,Boro Zone 256 | 255,Brooklyn,Williamsburg (North Side),Boro Zone 257 | 256,Brooklyn,Williamsburg (South Side),Boro Zone 258 | 257,Brooklyn,Windsor Terrace,Boro Zone 259 | 258,Queens,Woodhaven,Boro Zone 260 | 259,Bronx,Woodlawn/Wakefield,Boro Zone 261 | 260,Queens,Woodside,Boro Zone 262 | 261,Manhattan,World Trade Center,Yellow Zone 263 | 262,Manhattan,Yorkville East,Yellow Zone 264 | 263,Manhattan,Yorkville West,Yellow Zone 265 | 264,Unknown,NV,N/A 266 | 265,Unknown,NA,N/A -------------------------------------------------------------------------------- /data/yellow_tripdata_2022-01.parquet: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/risingwavelabs/risingwave-data-talks-workshop-2024-03-04/c35d3d9de58f174853b5f29439241c966d88964f/data/yellow_tripdata_2022-01.parquet -------------------------------------------------------------------------------- /docker/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:22.04 AS base 2 | 3 | ENV LANG en_US.utf8 4 | 5 | RUN apt-get update \ 6 | && apt-get -y install ca-certificates build-essential libsasl2-dev openjdk-11-jdk 7 | 8 | FROM base AS dashboard-builder 9 | 10 | RUN apt-get update && apt-get install -y curl gnupg protobuf-compiler && mkdir -p /etc/apt/keyrings \ 11 | && curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg \ 12 | && echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_18.x nodistro main" | tee /etc/apt/sources.list.d/nodesource.list \ 13 | && apt-get update && apt-get install -y nodejs 14 | 15 | COPY ./dashboard/ /risingwave/dashboard 16 | COPY ./proto /risingwave/proto 17 | 18 | RUN cd /risingwave/dashboard && npm i && npm run build-static && rm -rf node_modules 19 | 20 | FROM base AS rust-base 21 | 22 | RUN apt-get update && apt-get -y install make cmake protobuf-compiler curl bash lld unzip 23 | 24 | SHELL ["/bin/bash", "-c"] 25 | 26 | RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- --no-modify-path --default-toolchain none -y 27 | ENV PATH /root/.cargo/bin/:$PATH 28 | ENV CARGO_INCREMENTAL=0 29 | 30 | COPY rust-toolchain rust-toolchain 31 | 32 | # We need to add the `rustfmt` dependency, otherwise `risingwave_pb` will not compile 33 | RUN rustup self update \ 34 | && rustup set profile minimal \ 35 | && rustup show \ 36 | && rustup component add rustfmt \ 37 | && rustup target add wasm32-wasi 38 | 39 | RUN cargo install flamegraph 40 | # TODO: cargo-chef doesn't work well now, because we update Cargo.lock very often. 41 | # We may consider sccache instead. 42 | 43 | # RUN cargo install --git https://github.com/xxchan/cargo-chef cargo-chef --locked --rev 11f9fed 44 | 45 | # FROM rust-base AS rust-planner 46 | 47 | # RUN mkdir -p /risingwave 48 | # WORKDIR /risingwave 49 | # COPY ./ /risingwave 50 | 51 | # RUN cargo chef prepare --recipe-path recipe.json 52 | 53 | # FROM rust-base AS rust-builder 54 | 55 | # RUN mkdir -p /risingwave 56 | # WORKDIR /risingwave 57 | 58 | # COPY --from=rust-planner /risingwave/recipe.json recipe.json 59 | 60 | # # Build dependencies - this can be cached if the dependencies don't change 61 | # RUN cargo chef cook --release --recipe-path recipe.json 62 | 63 | FROM rust-base AS rust-builder 64 | 65 | # Build application 66 | ARG GIT_SHA 67 | ENV GIT_SHA=$GIT_SHA 68 | 69 | COPY ./ /risingwave 70 | WORKDIR /risingwave 71 | 72 | RUN cargo fetch && \ 73 | cargo build -p risingwave_cmd_all --release --features "rw-static-link" && \ 74 | mkdir -p /risingwave/bin && \ 75 | mv /risingwave/target/release/risingwave /risingwave/bin/ && \ 76 | mv /risingwave/target/release/risingwave.dwp /risingwave/bin/ && \ 77 | cp ./target/release/build/tikv-jemalloc-sys-*/out/build/bin/jeprof /risingwave/bin/ && \ 78 | chmod +x /risingwave/bin/jeprof && \ 79 | mkdir -p /risingwave/lib && cargo clean 80 | 81 | FROM base AS java-planner 82 | 83 | RUN mkdir -p /risingwave 84 | WORKDIR /risingwave 85 | 86 | COPY java /risingwave/java/ 87 | 88 | # Move java/**/pom.xml to poms/**/pom.xml 89 | RUN find . -name pom.xml -exec bash -c 'mkdir -p poms/$(dirname {}); mv {} poms/{}' \; 90 | 91 | # We use rust-maven-plugin to build java-binding. So it's FROM rust-base 92 | FROM rust-base AS java-builder 93 | 94 | RUN apt-get update && apt-get -y install maven 95 | 96 | RUN mkdir -p /risingwave 97 | WORKDIR /risingwave/java 98 | 99 | # 1. copy only poms 100 | COPY --from=java-planner /risingwave/poms /risingwave/java/ 101 | 102 | # 2. start downloading dependencies 103 | RUN mvn dependency:go-offline --fail-never 104 | 105 | # 3. add all source code and start compiling 106 | # TODO: only add java related code so that changing rust code won't recompile java code 107 | # Currently java-binding depends on the workspace Cargo.toml, which depends on the whole rust codebase 108 | # Besides, rust-maven-plugin sets --target-dir, so the dependencies are built twice. How to dedup? 109 | COPY ./ /risingwave 110 | 111 | RUN mvn -B package -Dmaven.test.skip=true -Dno-build-rust && \ 112 | mkdir -p /risingwave/bin/connector-node && \ 113 | tar -zxvf /risingwave/java/connector-node/assembly/target/risingwave-connector-1.0.0.tar.gz -C /risingwave/bin/connector-node 114 | 115 | FROM base AS risingwave 116 | 117 | LABEL org.opencontainers.image.source https://github.com/risingwavelabs/risingwave 118 | 119 | RUN apt-get update && apt-get -y install linux-tools-generic \ 120 | && ln -s "$(find /usr/lib/linux-tools/*/perf | head -1)" /usr/local/bin/perf 121 | 122 | RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get -y install gdb libpam-krb5 krb5-user telnet kafkacat \ 123 | && rm -rf /var/lib/{apt,dpkg,cache,log}/ 124 | 125 | RUN mkdir -p /risingwave/bin/connector-node && mkdir -p /risingwave/lib 126 | 127 | COPY --from=rust-builder /risingwave/bin/risingwave /risingwave/bin/risingwave 128 | COPY --from=rust-builder /risingwave/bin/risingwave.dwp /risingwave/bin/risingwave.dwp 129 | COPY --from=java-builder /risingwave/bin/connector-node /risingwave/bin/connector-node 130 | COPY --from=dashboard-builder /risingwave/dashboard/out /risingwave/ui 131 | COPY --from=rust-builder /risingwave/bin/jeprof /usr/local/bin/jeprof 132 | COPY --from=rust-base /root/.cargo/bin/flamegraph /usr/local/bin/flamegraph 133 | 134 | # Set default playground mode to docker-playground profile 135 | ENV PLAYGROUND_PROFILE docker-playground 136 | # Set default dashboard UI to local path instead of github proxy 137 | ENV RW_DASHBOARD_UI_PATH /risingwave/ui 138 | # Set default connector libs path 139 | ENV CONNECTOR_LIBS_PATH /risingwave/bin/connector-node/libs 140 | ENV IN_CONTAINER=1 141 | 142 | ENTRYPOINT [ "/risingwave/bin/risingwave" ] 143 | CMD [ "playground" ] 144 | -------------------------------------------------------------------------------- /docker/Dockerfile.hdfs: -------------------------------------------------------------------------------- 1 | FROM ubuntu:22.04 AS base 2 | 3 | ENV LANG en_US.utf8 4 | 5 | RUN apt-get update \ 6 | && apt-get -y install ca-certificates build-essential libsasl2-dev openjdk-11-jdk 7 | 8 | FROM base AS builder 9 | 10 | RUN apt-get update && apt-get -y install make cmake protobuf-compiler curl bash lld maven unzip 11 | 12 | SHELL ["/bin/bash", "-c"] 13 | 14 | RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- --no-modify-path --default-toolchain none -y 15 | 16 | RUN mkdir -p /risingwave 17 | 18 | WORKDIR /risingwave 19 | 20 | COPY ./ /risingwave 21 | COPY ./docker/hdfs_env.sh /risingwave/hdfs_env.sh 22 | 23 | ENV PATH /root/.cargo/bin/:$PATH 24 | 25 | ENV IN_CONTAINER=1 26 | 27 | ARG GIT_SHA 28 | ENV GIT_SHA=$GIT_SHA 29 | 30 | RUN curl -LO https://github.com/risingwavelabs/risingwave/archive/refs/heads/dashboard-artifact.zip 31 | RUN unzip dashboard-artifact.zip && mv risingwave-dashboard-artifact /risingwave/ui && rm dashboard-artifact.zip 32 | 33 | # We need to add the `rustfmt` dependency, otherwise `risingwave_pb` will not compile 34 | RUN rustup self update \ 35 | && rustup set profile minimal \ 36 | && rustup show \ 37 | && rustup component add rustfmt \ 38 | && rustup target add wasm32-wasi 39 | 40 | RUN cargo fetch 41 | 42 | # java home for hdrs 43 | ARG JAVA_HOME_PATH 44 | ENV JAVA_HOME ${JAVA_HOME_PATH} 45 | ENV LD_LIBRARY_PATH ${JAVA_HOME_PATH}/lib/server:${LD_LIBRARY_PATH} 46 | 47 | RUN cargo fetch && \ 48 | cargo build -p risingwave_cmd_all --release -p risingwave_object_store --features hdfs-backend --features "rw-static-link" && \ 49 | mkdir -p /risingwave/bin && \ 50 | mv /risingwave/target/release/risingwave /risingwave/bin/ && \ 51 | mv /risingwave/target/release/risingwave.dwp /risingwave/bin/ && \ 52 | cp ./target/release/build/tikv-jemalloc-sys-*/out/build/bin/jeprof /risingwave/bin/ && \ 53 | chmod +x /risingwave/bin/jeprof && \ 54 | mkdir -p /risingwave/lib && cargo clean 55 | 56 | RUN cd /risingwave/java && mvn -B package -Dmaven.test.skip=true -Dno-build-rust && \ 57 | mkdir -p /risingwave/bin/connector-node && \ 58 | tar -zxvf /risingwave/java/connector-node/assembly/target/risingwave-connector-1.0.0.tar.gz -C /risingwave/bin/connector-node 59 | 60 | FROM ubuntu:22.04 as image-base 61 | RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get -y install ca-certificates openjdk-11-jdk wget libsasl2-dev && rm -rf /var/lib/{apt,dpkg,cache,log}/ 62 | 63 | FROM image-base as risingwave 64 | LABEL org.opencontainers.image.source https://github.com/risingwavelabs/risingwave 65 | RUN mkdir -p /risingwave/bin/connector-node && mkdir -p /risingwave/lib 66 | COPY --from=builder /risingwave/bin/risingwave /risingwave/bin/risingwave 67 | COPY --from=builder /risingwave/bin/risingwave.dwp /risingwave/bin/risingwave.dwp 68 | COPY --from=builder /risingwave/bin/connector-node /risingwave/bin/connector-node 69 | COPY --from=builder /risingwave/ui /risingwave/ui 70 | COPY --from=builder /risingwave/hdfs_env.sh /risingwave/hdfs_env.sh 71 | RUN chmod +x /risingwave/hdfs_env.sh 72 | 73 | # hadoop 74 | RUN wget https://rw-yufan.s3.ap-southeast-1.amazonaws.com/hadoop-2.7.3.tar.gz -P /root/ 75 | RUN tar -zxvf /root/hadoop-2.7.3.tar.gz -C /opt/ 76 | RUN mv /opt/hadoop-2.7.3 /opt/hadoop 77 | RUN echo export HADOOP_HOME=/opt/hadoop/ >> ~/.bashrc 78 | RUN echo export PATH=$PATH:$HADOOP_HOME/bin:$HADOOP_HOME/sbin >> ~/.bashrc 79 | RUN echo export JAVA_HOME=$(readlink -f $(which java)) >> /opt/hadoop/etc/hadoop/yarn-env.sh 80 | RUN echo export JAVA_HOME=$(readlink -f $(which java)) >> /opt/hadoop/etc/hadoop/hadoop-env.sh 81 | RUN rm -rf ~/hadoop-2.7.3.tar.gz 82 | # java 83 | ENV HADOOP_HOME /opt/hadoop/ 84 | ENV PATH $PATH:$HADOOP_HOME/bin:$HADOOP_HOME/sbin 85 | ARG JAVA_HOME_PATH 86 | ENV JAVA_HOME ${JAVA_HOME_PATH} 87 | ENV LD_LIBRARY_PATH ${JAVA_HOME_PATH}/lib/server:${LD_LIBRARY_PATH} 88 | ENV HADOOP_CONF_DIR /opt/hadoop/etc/hadoop/ 89 | ENV CLASSPATH ${CLASSPATH} 90 | ENV CLASSPATH ${HADOOP_CONF_DIR}:${CLASSPATH} 91 | # Set default playground mode to docker-playground profile 92 | ENV PLAYGROUND_PROFILE docker-playground 93 | # Set default dashboard UI to local path instead of github proxy 94 | ENV RW_DASHBOARD_UI_PATH /risingwave/ui 95 | # Set default connector libs path 96 | ENV CONNECTOR_LIBS_PATH /risingwave/bin/connector-node/libs 97 | 98 | ENTRYPOINT [ "/risingwave/bin/risingwave" ] 99 | CMD [ "playground" ] 100 | -------------------------------------------------------------------------------- /docker/README.md: -------------------------------------------------------------------------------- 1 | # Docker Images 2 | 3 | ## Published images 4 | 5 | - `latest` on GHCR (latest nightly build): `ghcr.io/risingwavelabs/risingwave:latest` 6 | - `latest` on Docker Hub (latest release): `risingwavelabs/risingwave:latest` 7 | - Other tags available on both GHCR and Docker Hub: 8 | - `nightly-yyyyMMdd`, e.g., `nightly-20230108` 9 | - `vX.Y.Z`, e.g., `v0.1.15` 10 | 11 | ## Build the images 12 | 13 | The docker images for x86_64 are built with AVX2 SIMD extensions, while the images for aarch64 are built with NEON SIMD extensions. These must be available on your machine. If your machine does not support these extensions, you must build the docker image with the build-arg `simd_disabled=true`. 14 | 15 | To build the images, simply run: 16 | 17 | ``` 18 | docker build . -f docker/Dockerfile 19 | ``` 20 | 21 | from the project root. 22 | 23 | To build the images without SIMD vector extensions, run 24 | 25 | ``` 26 | docker build . -f docker/Dockerfile --build-arg simd_disabled=true 27 | ``` 28 | 29 | from the project root and run any subsequent docker commands on the resultant image. 30 | 31 | ## Use the images 32 | 33 | To ensure you are using the latest version of RisingWave image, 34 | 35 | ``` 36 | # Ensure risingwave image is of latest version 37 | docker pull ghcr.io/risingwavelabs/risingwave:latest 38 | ``` 39 | 40 | ### playground 41 | To start a RisingWave playground, run 42 | 43 | ``` 44 | # Start playground 45 | docker run -it --pull=always -p 4566:4566 -p 5691:5691 ghcr.io/risingwavelabs/risingwave:latest playground 46 | ``` 47 | 48 | ### standalone minio 49 | To start a RisingWave standalone mode with minio backend, run 50 | 51 | ``` 52 | # Start all components 53 | docker-compose up 54 | ``` 55 | 56 | ### distributed cluster minio 57 | To start a RisingWave cluster with minio backend, run 58 | 59 | ``` 60 | # Start all components 61 | docker-compose -f docker-compose-distributed.yml up 62 | ``` 63 | 64 | It will start a minio, a meta node, a compute node, a frontend, a compactor, a prometheus and a redpanda instance. 65 | 66 | ### s3 and other s3-compatible storage backend 67 | To start a RisingWave cluster with s3 backend, configure the aws credit in [aws.env](https://github.com/risingwavelabs/risingwave/blob/main/docker/aws.env). 68 | If you want to use some s3 compatible storage like Tencent Cloud COS, just configure one more [endpoint](https://github.com/risingwavelabs/risingwave/blob/a2684461e379ce73f8d730982147439e2379de16/docker/aws.env#L7). 69 | After configuring the environment and fill in your [bucket name](https://github.com/risingwavelabs/risingwave/blob/a2684461e379ce73f8d730982147439e2379de16/docker/docker-compose-with-s3.yml#L196), run 70 | 71 | ``` 72 | # Start all components 73 | docker-compose -f docker-compose-with-s3.yml up 74 | ``` 75 | 76 | It will run with s3 (compatible) object storage with a meta node, a compute node, a frontend, a compactor, a prometheus and a redpanda instance. 77 | 78 | ### Start with other storage products of public cloud vendors 79 | To start a RisingWave cluster with other storage backend, like Google Cloud Storage, Alicloud OSS or Azure Blob Storage, configure the authentication information in [multiple_object_storage.env](https://github.com/risingwavelabs/risingwave/blob/main/docker/multiple_object_storage.env), fill in your [bucket name](https://github.com/risingwavelabs/risingwave/blob/a2684461e379ce73f8d730982147439e2379de16/docker/docker-compose-with-gcs.yml#L196). 80 | and run 81 | 82 | ``` 83 | # Start all components 84 | docker-compose -f docker-compose-with-xxx.yml up 85 | ``` 86 | 87 | It will run RisingWave with corresponding (object) storage products. 88 | 89 | ### Start with HDFS backend 90 | To start a RisingWave cluster with HDFS, mount your `HADDOP_HOME` in [compactor node volumes](https://github.com/risingwavelabs/risingwave/blob/a2684461e379ce73f8d730982147439e2379de16/docker/docker-compose-with-hdfs.yml#L28), [compute node volumes](https://github.com/risingwavelabs/risingwave/blob/a2684461e379ce73f8d730982147439e2379de16/docker/docker-compose-with-hdfs.yml#L112) [compute node volumes](https://github.com/risingwavelabs/risingwave/blob/a2684461e379ce73f8d730982147439e2379de16/docker/docker-compose-with-hdfs.yml#L218), fill in the [cluster_name/namenode](https://github.com/risingwavelabs/risingwave/blob/a2684461e379ce73f8d730982147439e2379de16/docker/docker-compose-with-hdfs.yml#L202), 91 | and run 92 | 93 | ``` 94 | # Start all components 95 | docker-compose -f docker-compose-with-hdfs.yml up 96 | ``` 97 | 98 | It will run RisingWave with HDFS. 99 | 100 | To clean all data, run: 101 | 102 | ``` 103 | docker-compose down -v 104 | ``` 105 | 106 | > [!NOTE] 107 | > 108 | > For RisingWave kernel hackers, we always recommend using [risedev](../src/risedevtool/README.md) to start the full cluster, instead of using docker images. 109 | > See [CONTRIBUTING](../CONTRIBUTING.md) for more information. 110 | 111 | ## Generate docker-compose.yml 112 | 113 | ```bash 114 | ./risedev compose 115 | ``` 116 | 117 | ## Common Issues 118 | 119 | Error message: 120 | ``` 121 | Error { code: "XMinioStorageFull", message: "Storage backend has reached its minimum free drive threshold. Please delete a few objects to proceed." 122 | ``` 123 | 124 | Solution: 125 | This usually happens on MacOS with Docker Desktop. The Docker Deskup runs in the macOS Hypervisor. All the data, including logs, images, volumes, and so on, is stored in this hypervisor and the hypervisor has a default disk capacity limit. So when this message emerges, simply cleaning up the unused container or image can help mitigate. You can also increase capacity limit by clicking the Docker Desktop icon in the menu bar, then clicking Preferences > Resources > `Increase Disk image size`. 126 | -------------------------------------------------------------------------------- /docker/aws.env: -------------------------------------------------------------------------------- 1 | RUST_BACKTRACE="1" 2 | 3 | # The region of your object storage bucket 4 | AWS_REGION=your_region 5 | 6 | # The endpoint URL for your object storage, if you are using s3 compatible storage, uncomment the following lines. 7 | # RW_S3_ENDPOINT=your_endpoint 8 | 9 | # The access key ID for your object storage 10 | AWS_ACCESS_KEY_ID=your_access_key 11 | 12 | # The secret access key for your object storage 13 | AWS_SECRET_ACCESS_KEY=your_secret_key -------------------------------------------------------------------------------- /docker/aws/.gitignore: -------------------------------------------------------------------------------- 1 | risingwave 2 | -------------------------------------------------------------------------------- /docker/aws/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:22.04 2 | RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get -y install ca-certificates && rm -rf /var/lib/{apt,dpkg,cache,log}/ 3 | 4 | RUN mkdir -p /risingwave/bin 5 | COPY risingwave /risingwave/bin/risingwave 6 | ENTRYPOINT [ "/risingwave/bin/risingwave" ] 7 | CMD [ "playground" ] 8 | -------------------------------------------------------------------------------- /docker/aws/aws-build.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | 5 | export DOCKER_BUILDKIT=1 6 | DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" 7 | 8 | if ! [[ "$DIR" =~ ^/ebs.* ]] ; then 9 | echo "$(tput setaf 3)Warning: You're running build script in a non-persistent volume. Please refer to the guide and copy ~/risingwave to /ebs directory, and compile it in /ebs/risingwave, so that data won't be lost during EC2 re-create.$(tput sgr0)" 10 | fi 11 | 12 | cd "$DIR/../.." 13 | cargo build -p risingwave_cmd_all --release --features "rw-static-link" 14 | cp target/release/risingwave "$DIR/risingwave" 15 | 16 | cd "$DIR" 17 | docker build -t "${RW_REGISTRY}:latest" . 18 | docker push "${RW_REGISTRY}:latest" 19 | -------------------------------------------------------------------------------- /docker/dashboards/risingwave-user-dashboard.json: -------------------------------------------------------------------------------- 1 | {"__inputs":[],"annotations":{"list":[]},"description":"RisingWave Dashboard","editable":true,"gnetId":null,"graphTooltip":0,"hideControls":false,"id":null,"links":[],"panels":[{"cacheTimeout":null,"collapsed":true,"datasource":null,"description":null,"editable":true,"error":false,"fieldConfig":{"defaults":{"thresholds":{"mode":"absolute","steps":[]}}},"gridPos":{"h":1,"w":24,"x":0,"y":0},"height":null,"hideTimeOverride":false,"id":1,"interval":null,"links":[],"maxDataPoints":100,"maxPerRow":null,"minSpan":null,"panels":[{"cacheTimeout":null,"color":{"mode":"thresholds"},"columns":[],"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"description":"Information about actors","editable":true,"error":false,"fieldConfig":{"defaults":{"custom":{"align":"auto","displayMode":"auto","filterable":true},"thresholds":{"mode":"absolute","steps":[]},"unit":""},"overrides":[]},"fontSize":"100%","gridPos":{"h":8,"w":12,"x":0,"y":0},"height":null,"hideTimeOverride":false,"id":2,"interval":null,"links":[],"mappings":[],"maxDataPoints":100,"maxPerRow":null,"minSpan":null,"options":{"showHeader":true,"sortBy":[]},"repeat":null,"repeatDirection":null,"span":null,"targets":[{"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"expr":"group(actor_info{job=~\"$job\",instance=~\"$node\"}) by (actor_id, fragment_id, compute_node)","format":"table","hide":false,"instant":true,"interval":"","intervalFactor":2,"legendFormat":"","metric":"","query":"group(actor_info{job=~\"$job\",instance=~\"$node\"}) by (actor_id, fragment_id, compute_node)","refId":"","step":10,"target":""}],"timeFrom":null,"timeShift":null,"title":"Actor Info","transformations":[{"id":"organize","options":{"excludeByName":{"Time":true,"Value":true},"indexByName":{"actor_id":0,"compute_node":2,"fragment_id":1}}}],"transparent":false,"type":"table"},{"cacheTimeout":null,"color":{"mode":"thresholds"},"columns":[],"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"description":"Information about state tables. Column `materialized_view_id` is the id of the materialized view that this state table belongs to.","editable":true,"error":false,"fieldConfig":{"defaults":{"custom":{"align":"auto","displayMode":"auto","filterable":true},"thresholds":{"mode":"absolute","steps":[]},"unit":""},"overrides":[]},"fontSize":"100%","gridPos":{"h":8,"w":12,"x":12,"y":0},"height":null,"hideTimeOverride":false,"id":3,"interval":null,"links":[],"mappings":[],"maxDataPoints":100,"maxPerRow":null,"minSpan":null,"options":{"showHeader":true,"sortBy":[]},"repeat":null,"repeatDirection":null,"span":null,"targets":[{"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"expr":"group(table_info{job=~\"$job\",instance=~\"$node\"}) by (table_id, table_name, table_type, materialized_view_id, fragment_id, compaction_group_id)","format":"table","hide":false,"instant":true,"interval":"","intervalFactor":2,"legendFormat":"","metric":"","query":"group(table_info{job=~\"$job\",instance=~\"$node\"}) by (table_id, table_name, table_type, materialized_view_id, fragment_id, compaction_group_id)","refId":"","step":10,"target":""}],"timeFrom":null,"timeShift":null,"title":"State Table Info","transformations":[{"id":"organize","options":{"excludeByName":{"Time":true,"Value":true},"indexByName":{"compaction_group_id":5,"fragment_id":4,"materialized_view_id":3,"table_id":0,"table_name":1,"table_type":2}}}],"transparent":false,"type":"table"}],"repeat":null,"repeatDirection":null,"span":null,"targets":[],"timeFrom":null,"timeShift":null,"title":"Actor/Table Id Info","transformations":[],"transparent":false,"type":"row"},{"cacheTimeout":null,"collapsed":false,"datasource":null,"description":null,"editable":true,"error":false,"fieldConfig":{"defaults":{"thresholds":{"mode":"absolute","steps":[]}}},"gridPos":{"h":1,"w":24,"x":0,"y":1},"height":null,"hideTimeOverride":false,"id":4,"interval":null,"links":[],"maxDataPoints":100,"maxPerRow":null,"minSpan":null,"panels":[],"repeat":null,"repeatDirection":null,"span":null,"targets":[],"timeFrom":null,"timeShift":null,"title":"Overview","transformations":[],"transparent":false,"type":"row"},{"cacheTimeout":null,"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"description":"The figure shows the number of rows read by each source per second.","editable":true,"error":false,"fieldConfig":{"defaults":{"color":{"mode":"palette-classic"},"custom":{"axisLabel":"","axisPlacement":"auto","axisSoftMax":null,"axisSoftMin":null,"barAlignment":0,"drawStyle":"line","fillOpacity":10,"gradientMode":"none","hideFrom":{"legend":false,"tooltip":false,"viz":false},"lineInterpolation":"linear","lineWidth":1,"pointSize":5,"scaleDistribution":{"log":2,"type":"linear"},"showPoints":"auto","spanNulls":false,"stacking":{},"thresholdsStyle":{"mode":"off"}},"decimals":null,"mappings":[],"max":null,"min":null,"thresholds":{"mode":"absolute","steps":[]},"unit":"rows/s"},"overrides":[]},"gridPos":{"h":8,"w":12,"x":0,"y":2},"height":null,"hideTimeOverride":false,"id":5,"interval":"1s","links":[],"maxDataPoints":1000,"maxPerRow":null,"minSpan":null,"options":{"legend":{"calcs":["mean"],"displayMode":"table","placement":"bottom"},"tooltip":{"mode":"single","sort":"none"}},"repeat":null,"repeatDirection":null,"span":null,"targets":[{"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"expr":"sum(rate(stream_source_output_rows_counts{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])) by (source_id, source_name, fragment_id)","format":"time_series","hide":false,"instant":false,"interval":"","intervalFactor":2,"legendFormat":"{{source_id}} {{source_name}} (fragment {{fragment_id}})","metric":"","query":"sum(rate(stream_source_output_rows_counts{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])) by (source_id, source_name, fragment_id)","refId":"","step":10,"target":""}],"timeFrom":null,"timeShift":null,"title":"Source Throughput(rows/s)","transformations":[],"transparent":false,"type":"timeseries"},{"cacheTimeout":null,"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"description":"The figure shows the number of bytes read by each source per second.","editable":true,"error":false,"fieldConfig":{"defaults":{"color":{"mode":"palette-classic"},"custom":{"axisLabel":"","axisPlacement":"auto","axisSoftMax":null,"axisSoftMin":null,"barAlignment":0,"drawStyle":"line","fillOpacity":10,"gradientMode":"none","hideFrom":{"legend":false,"tooltip":false,"viz":false},"lineInterpolation":"linear","lineWidth":1,"pointSize":5,"scaleDistribution":{"log":2,"type":"linear"},"showPoints":"auto","spanNulls":false,"stacking":{},"thresholdsStyle":{"mode":"off"}},"decimals":null,"mappings":[],"max":null,"min":null,"thresholds":{"mode":"absolute","steps":[]},"unit":"MB/s"},"overrides":[]},"gridPos":{"h":8,"w":12,"x":12,"y":2},"height":null,"hideTimeOverride":false,"id":6,"interval":"1s","links":[],"maxDataPoints":1000,"maxPerRow":null,"minSpan":null,"options":{"legend":{"calcs":["mean"],"displayMode":"table","placement":"bottom"},"tooltip":{"mode":"single","sort":"none"}},"repeat":null,"repeatDirection":null,"span":null,"targets":[{"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"expr":"(sum by (source_id, source_name, fragment_id)(rate(source_partition_input_bytes{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])))/(1000*1000)","format":"time_series","hide":false,"instant":false,"interval":"","intervalFactor":2,"legendFormat":"{{source_id}} {{source_name}} (fragment {{fragment_id}})","metric":"","query":"(sum by (source_id, source_name, fragment_id)(rate(source_partition_input_bytes{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])))/(1000*1000)","refId":"","step":10,"target":""}],"timeFrom":null,"timeShift":null,"title":"Source Throughput(MB/s)","transformations":[],"transparent":false,"type":"timeseries"},{"cacheTimeout":null,"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"description":"The number of rows streamed into each sink per second.","editable":true,"error":false,"fieldConfig":{"defaults":{"color":{"mode":"palette-classic"},"custom":{"axisLabel":"","axisPlacement":"auto","axisSoftMax":null,"axisSoftMin":null,"barAlignment":0,"drawStyle":"line","fillOpacity":10,"gradientMode":"none","hideFrom":{"legend":false,"tooltip":false,"viz":false},"lineInterpolation":"linear","lineWidth":1,"pointSize":5,"scaleDistribution":{"log":2,"type":"linear"},"showPoints":"auto","spanNulls":false,"stacking":{},"thresholdsStyle":{"mode":"off"}},"decimals":null,"mappings":[],"max":null,"min":null,"thresholds":{"mode":"absolute","steps":[]},"unit":"rows/s"},"overrides":[]},"gridPos":{"h":8,"w":12,"x":0,"y":10},"height":null,"hideTimeOverride":false,"id":7,"interval":"1s","links":[],"maxDataPoints":1000,"maxPerRow":null,"minSpan":null,"options":{"legend":{"calcs":["mean"],"displayMode":"table","placement":"bottom"},"tooltip":{"mode":"single","sort":"none"}},"repeat":null,"repeatDirection":null,"span":null,"targets":[{"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"expr":"sum(rate(stream_sink_input_row_count{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])) by (sink_id) * on(sink_id) group_left(sink_name) group(sink_info{job=~\"$job\",instance=~\"$node\"}) by (sink_id, sink_name)","format":"time_series","hide":false,"instant":false,"interval":"","intervalFactor":2,"legendFormat":"sink {{sink_id}} {{sink_name}}","metric":"","query":"sum(rate(stream_sink_input_row_count{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])) by (sink_id) * on(sink_id) group_left(sink_name) group(sink_info{job=~\"$job\",instance=~\"$node\"}) by (sink_id, sink_name)","refId":"","step":10,"target":""}],"timeFrom":null,"timeShift":null,"title":"Sink Throughput(rows/s)","transformations":[],"transparent":false,"type":"timeseries"},{"cacheTimeout":null,"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"description":"The figure shows the number of rows written into each materialized view per second.","editable":true,"error":false,"fieldConfig":{"defaults":{"color":{"mode":"palette-classic"},"custom":{"axisLabel":"","axisPlacement":"auto","axisSoftMax":null,"axisSoftMin":null,"barAlignment":0,"drawStyle":"line","fillOpacity":10,"gradientMode":"none","hideFrom":{"legend":false,"tooltip":false,"viz":false},"lineInterpolation":"linear","lineWidth":1,"pointSize":5,"scaleDistribution":{"log":2,"type":"linear"},"showPoints":"auto","spanNulls":false,"stacking":{},"thresholdsStyle":{"mode":"off"}},"decimals":null,"mappings":[],"max":null,"min":null,"thresholds":{"mode":"absolute","steps":[]},"unit":"rows/s"},"overrides":[]},"gridPos":{"h":8,"w":12,"x":12,"y":10},"height":null,"hideTimeOverride":false,"id":8,"interval":"1s","links":[],"maxDataPoints":1000,"maxPerRow":null,"minSpan":null,"options":{"legend":{"calcs":["mean"],"displayMode":"table","placement":"bottom"},"tooltip":{"mode":"single","sort":"none"}},"repeat":null,"repeatDirection":null,"span":null,"targets":[{"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"expr":"sum(rate(stream_mview_input_row_count{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])) by (table_id) * on(table_id) group_left(table_name) group(table_info{job=~\"$job\",instance=~\"$node\"}) by (table_id, table_name)","format":"time_series","hide":false,"instant":false,"interval":"","intervalFactor":2,"legendFormat":"mview {{table_id}} {{table_name}}","metric":"","query":"sum(rate(stream_mview_input_row_count{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])) by (table_id) * on(table_id) group_left(table_name) group(table_info{job=~\"$job\",instance=~\"$node\"}) by (table_id, table_name)","refId":"","step":10,"target":""}],"timeFrom":null,"timeShift":null,"title":"Materialized View Throughput(rows/s)","transformations":[],"transparent":false,"type":"timeseries"},{"cacheTimeout":null,"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"description":"The time that the data between two consecutive barriers gets fully processed, i.e. the computation results are made durable into materialized views or sink to external systems. This metric shows to users the freshness of materialized views.","editable":true,"error":false,"fieldConfig":{"defaults":{"color":{"mode":"palette-classic"},"custom":{"axisLabel":"","axisPlacement":"auto","axisSoftMax":null,"axisSoftMin":null,"barAlignment":0,"drawStyle":"line","fillOpacity":10,"gradientMode":"none","hideFrom":{"legend":false,"tooltip":false,"viz":false},"lineInterpolation":"linear","lineWidth":1,"pointSize":5,"scaleDistribution":{"log":2,"type":"linear"},"showPoints":"auto","spanNulls":false,"stacking":{},"thresholdsStyle":{"mode":"off"}},"decimals":null,"mappings":[],"max":null,"min":null,"thresholds":{"mode":"absolute","steps":[]},"unit":"s"},"overrides":[]},"gridPos":{"h":8,"w":12,"x":0,"y":18},"height":null,"hideTimeOverride":false,"id":9,"interval":"1s","links":[],"maxDataPoints":1000,"maxPerRow":null,"minSpan":null,"options":{"legend":{"calcs":["mean"],"displayMode":"table","placement":"bottom"},"tooltip":{"mode":"single","sort":"none"}},"repeat":null,"repeatDirection":null,"span":null,"targets":[{"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"expr":"histogram_quantile(0.5, sum(rate(meta_barrier_duration_seconds_bucket{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])) by (le))","format":"time_series","hide":false,"instant":false,"interval":"","intervalFactor":2,"legendFormat":"barrier_latency_p50","metric":"","query":"histogram_quantile(0.5, sum(rate(meta_barrier_duration_seconds_bucket{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])) by (le))","refId":"","step":10,"target":""},{"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"expr":"histogram_quantile(0.99, sum(rate(meta_barrier_duration_seconds_bucket{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])) by (le))","format":"time_series","hide":false,"instant":false,"interval":"","intervalFactor":2,"legendFormat":"barrier_latency_p99","metric":"","query":"histogram_quantile(0.99, sum(rate(meta_barrier_duration_seconds_bucket{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])) by (le))","refId":"","step":10,"target":""},{"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"expr":"rate(meta_barrier_duration_seconds_sum{job=~\"$job\",instance=~\"$node\"}[$__rate_interval]) / rate(meta_barrier_duration_seconds_count{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])","format":"time_series","hide":false,"instant":false,"interval":"","intervalFactor":2,"legendFormat":"barrier_latency_avg","metric":"","query":"rate(meta_barrier_duration_seconds_sum{job=~\"$job\",instance=~\"$node\"}[$__rate_interval]) / rate(meta_barrier_duration_seconds_count{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])","refId":"","step":10,"target":""}],"timeFrom":null,"timeShift":null,"title":"Barrier Latency","transformations":[],"transparent":false,"type":"timeseries"},{"cacheTimeout":null,"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"description":"Alerts in the system group by type:\n - Too Many Barriers: there are too many uncommitted barriers generated. This means the streaming graph is stuck or under heavy load. Check 'Barrier Latency' panel.\n - Recovery Triggered: cluster recovery is triggered. Check 'Errors by Type' / 'Node Count' panels.\n - Lagging Version: the checkpointed or pinned version id is lagging behind the current version id. Check 'Hummock Manager' section in dev dashboard.\n - Lagging Epoch: the pinned or safe epoch is lagging behind the current max committed epoch. Check 'Hummock Manager' section in dev dashboard.\n - Lagging Compaction: there are too many files in L0. This can be caused by compactor failure or lag of compactor resource. Check 'Compaction' section in dev dashboard.\n - Lagging Vacuum: there are too many stale files waiting to be cleaned. This can be caused by compactor failure or lag of compactor resource. Check 'Compaction' section in dev dashboard.\n - Abnormal Meta Cache Memory: the meta cache memory usage is too large, exceeding the expected 10 percent.\n - Abnormal Block Cache Memory: the block cache memory usage is too large, exceeding the expected 10 percent.\n - Abnormal Uploading Memory Usage: uploading memory is more than 70 percent of the expected, and is about to spill.\n - Write Stall: Compaction cannot keep up. Stall foreground write.\n ","editable":true,"error":false,"fieldConfig":{"defaults":{"color":{"mode":"palette-classic"},"custom":{"axisLabel":"","axisPlacement":"auto","axisSoftMax":null,"axisSoftMin":null,"barAlignment":0,"drawStyle":"line","fillOpacity":10,"gradientMode":"none","hideFrom":{"legend":false,"tooltip":false,"viz":false},"lineInterpolation":"linear","lineWidth":1,"pointSize":5,"scaleDistribution":{"log":2,"type":"linear"},"showPoints":"auto","spanNulls":false,"stacking":{},"thresholdsStyle":{"mode":"off"}},"decimals":null,"mappings":[],"max":null,"min":null,"thresholds":{"mode":"absolute","steps":[]},"unit":""},"overrides":[]},"gridPos":{"h":8,"w":12,"x":12,"y":18},"height":null,"hideTimeOverride":false,"id":10,"interval":"1s","links":[],"maxDataPoints":1000,"maxPerRow":null,"minSpan":null,"options":{"legend":{"calcs":["last"],"displayMode":"table","placement":"bottom"},"tooltip":{"mode":"single","sort":"none"}},"repeat":null,"repeatDirection":null,"span":null,"targets":[{"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"expr":"all_barrier_nums{job=~\"$job\",instance=~\"$node\"} >= bool 200","format":"time_series","hide":false,"instant":false,"interval":"","intervalFactor":2,"legendFormat":"Too Many Barriers","metric":"","query":"all_barrier_nums{job=~\"$job\",instance=~\"$node\"} >= bool 200","refId":"","step":10,"target":""},{"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"expr":"sum(rate(recovery_latency_count{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])) > bool 0 + sum(recovery_failure_cnt{job=~\"$job\",instance=~\"$node\"}) > bool 0","format":"time_series","hide":false,"instant":false,"interval":"","intervalFactor":2,"legendFormat":"Recovery Triggered","metric":"","query":"sum(rate(recovery_latency_count{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])) > bool 0 + sum(recovery_failure_cnt{job=~\"$job\",instance=~\"$node\"}) > bool 0","refId":"","step":10,"target":""},{"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"expr":"((storage_current_version_id{job=~\"$job\",instance=~\"$node\"} - storage_checkpoint_version_id{job=~\"$job\",instance=~\"$node\"}) >= bool 100) + ((storage_current_version_id{job=~\"$job\",instance=~\"$node\"} - storage_min_pinned_version_id{job=~\"$job\",instance=~\"$node\"}) >= bool 100)","format":"time_series","hide":false,"instant":false,"interval":"","intervalFactor":2,"legendFormat":"Lagging Version","metric":"","query":"((storage_current_version_id{job=~\"$job\",instance=~\"$node\"} - storage_checkpoint_version_id{job=~\"$job\",instance=~\"$node\"}) >= bool 100) + ((storage_current_version_id{job=~\"$job\",instance=~\"$node\"} - storage_min_pinned_version_id{job=~\"$job\",instance=~\"$node\"}) >= bool 100)","refId":"","step":10,"target":""},{"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"expr":"((storage_max_committed_epoch{job=~\"$job\",instance=~\"$node\"} - storage_min_pinned_epoch{job=~\"$job\",instance=~\"$node\"}) >= bool 6553600000 unless + storage_min_pinned_epoch{job=~\"$job\",instance=~\"$node\"} == 0)","format":"time_series","hide":false,"instant":false,"interval":"","intervalFactor":2,"legendFormat":"Lagging Epoch","metric":"","query":"((storage_max_committed_epoch{job=~\"$job\",instance=~\"$node\"} - storage_min_pinned_epoch{job=~\"$job\",instance=~\"$node\"}) >= bool 6553600000 unless + storage_min_pinned_epoch{job=~\"$job\",instance=~\"$node\"} == 0)","refId":"","step":10,"target":""},{"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"expr":"sum(label_replace(storage_level_sst_num{job=~\"$job\",instance=~\"$node\"}, 'L0', 'L0', 'level_index', '.*_L0') unless storage_level_sst_num{job=~\"$job\",instance=~\"$node\"}) by (L0) >= bool 200","format":"time_series","hide":false,"instant":false,"interval":"","intervalFactor":2,"legendFormat":"Lagging Compaction","metric":"","query":"sum(label_replace(storage_level_sst_num{job=~\"$job\",instance=~\"$node\"}, 'L0', 'L0', 'level_index', '.*_L0') unless storage_level_sst_num{job=~\"$job\",instance=~\"$node\"}) by (L0) >= bool 200","refId":"","step":10,"target":""},{"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"expr":"storage_stale_object_count{job=~\"$job\",instance=~\"$node\"} >= bool 200","format":"time_series","hide":false,"instant":false,"interval":"","intervalFactor":2,"legendFormat":"Lagging Vacuum","metric":"","query":"storage_stale_object_count{job=~\"$job\",instance=~\"$node\"} >= bool 200","refId":"","step":10,"target":""},{"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"expr":"state_store_meta_cache_usage_ratio{job=~\"$job\",instance=~\"$node\"} >= bool 1.1","format":"time_series","hide":false,"instant":false,"interval":"","intervalFactor":2,"legendFormat":"Abnormal Meta Cache Memory","metric":"","query":"state_store_meta_cache_usage_ratio{job=~\"$job\",instance=~\"$node\"} >= bool 1.1","refId":"","step":10,"target":""},{"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"expr":"state_store_block_cache_usage_ratio{job=~\"$job\",instance=~\"$node\"} >= bool 1.1","format":"time_series","hide":false,"instant":false,"interval":"","intervalFactor":2,"legendFormat":"Abnormal Block Cache Memory","metric":"","query":"state_store_block_cache_usage_ratio{job=~\"$job\",instance=~\"$node\"} >= bool 1.1","refId":"","step":10,"target":""},{"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"expr":"state_store_uploading_memory_usage_ratio{job=~\"$job\",instance=~\"$node\"} >= bool 0.7","format":"time_series","hide":false,"instant":false,"interval":"","intervalFactor":2,"legendFormat":"Abnormal Uploading Memory Usage","metric":"","query":"state_store_uploading_memory_usage_ratio{job=~\"$job\",instance=~\"$node\"} >= bool 0.7","refId":"","step":10,"target":""},{"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"expr":"storage_write_stop_compaction_groups{job=~\"$job\",instance=~\"$node\"} > bool 0","format":"time_series","hide":false,"instant":false,"interval":"","intervalFactor":2,"legendFormat":"Write Stall","metric":"","query":"storage_write_stop_compaction_groups{job=~\"$job\",instance=~\"$node\"} > bool 0","refId":"","step":10,"target":""}],"timeFrom":null,"timeShift":null,"title":"Alerts","transformations":[],"transparent":false,"type":"timeseries"},{"cacheTimeout":null,"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"description":"Errors in the system group by type","editable":true,"error":false,"fieldConfig":{"defaults":{"color":{"mode":"palette-classic"},"custom":{"axisLabel":"","axisPlacement":"auto","axisSoftMax":null,"axisSoftMin":null,"barAlignment":0,"drawStyle":"line","fillOpacity":10,"gradientMode":"none","hideFrom":{"legend":false,"tooltip":false,"viz":false},"lineInterpolation":"linear","lineWidth":1,"pointSize":5,"scaleDistribution":{"log":2,"type":"linear"},"showPoints":"auto","spanNulls":false,"stacking":{},"thresholdsStyle":{"mode":"off"}},"decimals":null,"mappings":[],"max":null,"min":null,"thresholds":{"mode":"absolute","steps":[]},"unit":""},"overrides":[]},"gridPos":{"h":8,"w":12,"x":0,"y":26},"height":null,"hideTimeOverride":false,"id":11,"interval":"1s","links":[],"maxDataPoints":1000,"maxPerRow":null,"minSpan":null,"options":{"legend":{"calcs":["mean"],"displayMode":"table","placement":"bottom"},"tooltip":{"mode":"single","sort":"none"}},"repeat":null,"repeatDirection":null,"span":null,"targets":[{"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"expr":"sum(user_compute_error_count{job=~\"$job\",instance=~\"$node\"}) by (error_type, error_msg, fragment_id, executor_name)","format":"time_series","hide":false,"instant":false,"interval":"","intervalFactor":2,"legendFormat":"compute error {{error_type}}: {{error_msg}} ({{executor_name}}: fragment_id={{fragment_id}})","metric":"","query":"sum(user_compute_error_count{job=~\"$job\",instance=~\"$node\"}) by (error_type, error_msg, fragment_id, executor_name)","refId":"","step":10,"target":""},{"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"expr":"sum(user_source_error_count{job=~\"$job\",instance=~\"$node\"}) by (error_type, error_msg, fragment_id, table_id, executor_name)","format":"time_series","hide":false,"instant":false,"interval":"","intervalFactor":2,"legendFormat":"parse error {{error_type}}: {{error_msg}} ({{executor_name}}: table_id={{table_id}}, fragment_id={{fragment_id}})","metric":"","query":"sum(user_source_error_count{job=~\"$job\",instance=~\"$node\"}) by (error_type, error_msg, fragment_id, table_id, executor_name)","refId":"","step":10,"target":""},{"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"expr":"source_status_is_up{job=~\"$job\",instance=~\"$node\"} == 0","format":"time_series","hide":false,"instant":false,"interval":"","intervalFactor":2,"legendFormat":"source error: source_id={{source_id}}, source_name={{source_name}} @ {{instance}}","metric":"","query":"source_status_is_up{job=~\"$job\",instance=~\"$node\"} == 0","refId":"","step":10,"target":""},{"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"expr":"sum(rate(object_store_failure_count{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])) by (instance, job, type)","format":"time_series","hide":false,"instant":false,"interval":"","intervalFactor":2,"legendFormat":"remote storage error {{type}}: {{job}} @ {{instance}}","metric":"","query":"sum(rate(object_store_failure_count{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])) by (instance, job, type)","refId":"","step":10,"target":""}],"timeFrom":null,"timeShift":null,"title":"Errors","transformations":[],"transparent":false,"type":"timeseries"},{"cacheTimeout":null,"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"description":"","editable":true,"error":false,"fieldConfig":{"defaults":{"color":{"mode":"palette-classic"},"custom":{"axisLabel":"","axisPlacement":"auto","axisSoftMax":null,"axisSoftMin":null,"barAlignment":0,"drawStyle":"line","fillOpacity":10,"gradientMode":"none","hideFrom":{"legend":false,"tooltip":false,"viz":false},"lineInterpolation":"linear","lineWidth":1,"pointSize":5,"scaleDistribution":{"log":2,"type":"linear"},"showPoints":"auto","spanNulls":false,"stacking":{},"thresholdsStyle":{"mode":"off"}},"decimals":null,"mappings":[],"max":null,"min":null,"thresholds":{"mode":"absolute","steps":[]},"unit":"Qps"},"overrides":[]},"gridPos":{"h":8,"w":12,"x":12,"y":26},"height":null,"hideTimeOverride":false,"id":12,"interval":"1s","links":[],"maxDataPoints":1000,"maxPerRow":null,"minSpan":null,"options":{"legend":{"calcs":["mean"],"displayMode":"table","placement":"bottom"},"tooltip":{"mode":"single","sort":"none"}},"repeat":null,"repeatDirection":null,"span":null,"targets":[{"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"expr":"rate(frontend_query_counter_local_execution{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])","format":"time_series","hide":false,"instant":false,"interval":"","intervalFactor":2,"legendFormat":"Local mode","metric":"","query":"rate(frontend_query_counter_local_execution{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])","refId":"","step":10,"target":""},{"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"expr":"rate(distributed_completed_query_counter{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])","format":"time_series","hide":false,"instant":false,"interval":"","intervalFactor":2,"legendFormat":"Distributed mode","metric":"","query":"rate(distributed_completed_query_counter{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])","refId":"","step":10,"target":""}],"timeFrom":null,"timeShift":null,"title":"Batch Query QPS","transformations":[],"transparent":false,"type":"timeseries"},{"cacheTimeout":null,"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"description":"The number of each type of RisingWave components alive.","editable":true,"error":false,"fieldConfig":{"defaults":{"color":{"mode":"palette-classic"},"custom":{"axisLabel":"","axisPlacement":"auto","axisSoftMax":null,"axisSoftMin":null,"barAlignment":0,"drawStyle":"line","fillOpacity":10,"gradientMode":"none","hideFrom":{"legend":false,"tooltip":false,"viz":false},"lineInterpolation":"linear","lineWidth":1,"pointSize":5,"scaleDistribution":{"log":2,"type":"linear"},"showPoints":"auto","spanNulls":false,"stacking":{},"thresholdsStyle":{"mode":"off"}},"decimals":null,"mappings":[],"max":null,"min":null,"thresholds":{"mode":"absolute","steps":[]},"unit":""},"overrides":[]},"gridPos":{"h":8,"w":12,"x":0,"y":34},"height":null,"hideTimeOverride":false,"id":13,"interval":"1s","links":[],"maxDataPoints":1000,"maxPerRow":null,"minSpan":null,"options":{"legend":{"calcs":["last"],"displayMode":"table","placement":"bottom"},"tooltip":{"mode":"single","sort":"none"}},"repeat":null,"repeatDirection":null,"span":null,"targets":[{"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"expr":"sum(worker_num{job=~\"$job\",instance=~\"$node\"}) by (worker_type)","format":"time_series","hide":false,"instant":false,"interval":"","intervalFactor":2,"legendFormat":"{{worker_type}}","metric":"","query":"sum(worker_num{job=~\"$job\",instance=~\"$node\"}) by (worker_type)","refId":"","step":10,"target":""}],"timeFrom":null,"timeShift":null,"title":"Node Count","transformations":[],"transparent":false,"type":"timeseries"},{"cacheTimeout":null,"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"description":"Number of active sessions in frontend nodes","editable":true,"error":false,"fieldConfig":{"defaults":{"color":{"mode":"palette-classic"},"custom":{"axisLabel":"","axisPlacement":"auto","axisSoftMax":null,"axisSoftMin":null,"barAlignment":0,"drawStyle":"line","fillOpacity":10,"gradientMode":"none","hideFrom":{"legend":false,"tooltip":false,"viz":false},"lineInterpolation":"linear","lineWidth":1,"pointSize":5,"scaleDistribution":{"log":2,"type":"linear"},"showPoints":"auto","spanNulls":false,"stacking":{},"thresholdsStyle":{"mode":"off"}},"decimals":null,"mappings":[],"max":null,"min":null,"thresholds":{"mode":"absolute","steps":[]},"unit":""},"overrides":[]},"gridPos":{"h":8,"w":12,"x":12,"y":34},"height":null,"hideTimeOverride":false,"id":14,"interval":"1s","links":[],"maxDataPoints":1000,"maxPerRow":null,"minSpan":null,"options":{"legend":{"calcs":["mean"],"displayMode":"table","placement":"bottom"},"tooltip":{"mode":"single","sort":"none"}},"repeat":null,"repeatDirection":null,"span":null,"targets":[{"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"expr":"frontend_active_sessions{job=~\"$job\",instance=~\"$node\"}","format":"time_series","hide":false,"instant":false,"interval":"","intervalFactor":2,"legendFormat":"","metric":"","query":"frontend_active_sessions{job=~\"$job\",instance=~\"$node\"}","refId":"","step":10,"target":""}],"timeFrom":null,"timeShift":null,"title":"Active Sessions","transformations":[],"transparent":false,"type":"timeseries"},{"cacheTimeout":null,"collapsed":true,"datasource":null,"description":null,"editable":true,"error":false,"fieldConfig":{"defaults":{"thresholds":{"mode":"absolute","steps":[]}}},"gridPos":{"h":1,"w":24,"x":0,"y":42},"height":null,"hideTimeOverride":false,"id":15,"interval":null,"links":[],"maxDataPoints":100,"maxPerRow":null,"minSpan":null,"panels":[{"cacheTimeout":null,"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"description":"The CPU usage of each RisingWave component.","editable":true,"error":false,"fieldConfig":{"defaults":{"color":{"mode":"palette-classic"},"custom":{"axisLabel":"","axisPlacement":"auto","axisSoftMax":null,"axisSoftMin":null,"barAlignment":0,"drawStyle":"line","fillOpacity":10,"gradientMode":"none","hideFrom":{"legend":false,"tooltip":false,"viz":false},"lineInterpolation":"linear","lineWidth":1,"pointSize":5,"scaleDistribution":{"log":2,"type":"linear"},"showPoints":"auto","spanNulls":false,"stacking":{},"thresholdsStyle":{"mode":"off"}},"decimals":null,"mappings":[],"max":null,"min":null,"thresholds":{"mode":"absolute","steps":[]},"unit":"percentunit"},"overrides":[]},"gridPos":{"h":8,"w":12,"x":0,"y":0},"height":null,"hideTimeOverride":false,"id":16,"interval":"1s","links":[],"maxDataPoints":1000,"maxPerRow":null,"minSpan":null,"options":{"legend":{"calcs":[],"displayMode":"table","placement":"bottom"},"tooltip":{"mode":"single","sort":"none"}},"repeat":null,"repeatDirection":null,"span":null,"targets":[{"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"expr":"sum(rate(process_cpu_seconds_total{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])) by (instance)","format":"time_series","hide":false,"instant":false,"interval":"","intervalFactor":2,"legendFormat":"{{instance}}","metric":"","query":"sum(rate(process_cpu_seconds_total{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])) by (instance)","refId":"","step":10,"target":""}],"timeFrom":null,"timeShift":null,"title":"Node CPU Usage","transformations":[],"transparent":false,"type":"timeseries"},{"cacheTimeout":null,"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"description":"Number of CPU cores per RisingWave component.","editable":true,"error":false,"fieldConfig":{"defaults":{"color":{"mode":"palette-classic"},"custom":{"axisLabel":"","axisPlacement":"auto","axisSoftMax":null,"axisSoftMin":null,"barAlignment":0,"drawStyle":"line","fillOpacity":10,"gradientMode":"none","hideFrom":{"legend":false,"tooltip":false,"viz":false},"lineInterpolation":"linear","lineWidth":1,"pointSize":5,"scaleDistribution":{"log":2,"type":"linear"},"showPoints":"auto","spanNulls":false,"stacking":{},"thresholdsStyle":{"mode":"off"}},"decimals":null,"mappings":[],"max":null,"min":null,"thresholds":{"mode":"absolute","steps":[]},"unit":""},"overrides":[]},"gridPos":{"h":8,"w":12,"x":12,"y":0},"height":null,"hideTimeOverride":false,"id":17,"interval":"1s","links":[],"maxDataPoints":1000,"maxPerRow":null,"minSpan":null,"options":{"legend":{"calcs":["mean"],"displayMode":"table","placement":"bottom"},"tooltip":{"mode":"single","sort":"none"}},"repeat":null,"repeatDirection":null,"span":null,"targets":[{"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"expr":"avg(process_cpu_core_num{job=~\"$job\",instance=~\"$node\"}) by (instance)","format":"time_series","hide":false,"instant":false,"interval":"","intervalFactor":2,"legendFormat":"{{instance}}","metric":"","query":"avg(process_cpu_core_num{job=~\"$job\",instance=~\"$node\"}) by (instance)","refId":"","step":10,"target":""}],"timeFrom":null,"timeShift":null,"title":"Node CPU Core Number","transformations":[],"transparent":false,"type":"timeseries"}],"repeat":null,"repeatDirection":null,"span":null,"targets":[],"timeFrom":null,"timeShift":null,"title":"CPU","transformations":[],"transparent":false,"type":"row"},{"cacheTimeout":null,"collapsed":true,"datasource":null,"description":null,"editable":true,"error":false,"fieldConfig":{"defaults":{"thresholds":{"mode":"absolute","steps":[]}}},"gridPos":{"h":1,"w":24,"x":0,"y":43},"height":null,"hideTimeOverride":false,"id":18,"interval":null,"links":[],"maxDataPoints":100,"maxPerRow":null,"minSpan":null,"panels":[{"cacheTimeout":null,"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"description":"The memory usage of each RisingWave component.","editable":true,"error":false,"fieldConfig":{"defaults":{"color":{"mode":"palette-classic"},"custom":{"axisLabel":"","axisPlacement":"auto","axisSoftMax":null,"axisSoftMin":null,"barAlignment":0,"drawStyle":"line","fillOpacity":10,"gradientMode":"none","hideFrom":{"legend":false,"tooltip":false,"viz":false},"lineInterpolation":"linear","lineWidth":1,"pointSize":5,"scaleDistribution":{"log":2,"type":"linear"},"showPoints":"auto","spanNulls":false,"stacking":{},"thresholdsStyle":{"mode":"off"}},"decimals":null,"mappings":[],"max":null,"min":null,"thresholds":{"mode":"absolute","steps":[]},"unit":"bytes"},"overrides":[]},"gridPos":{"h":8,"w":12,"x":0,"y":0},"height":null,"hideTimeOverride":false,"id":19,"interval":"1s","links":[],"maxDataPoints":1000,"maxPerRow":null,"minSpan":null,"options":{"legend":{"calcs":[],"displayMode":"table","placement":"bottom"},"tooltip":{"mode":"single","sort":"none"}},"repeat":null,"repeatDirection":null,"span":null,"targets":[{"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"expr":"avg(process_resident_memory_bytes{job=~\"$job\",instance=~\"$node\"}) by (job,instance)","format":"time_series","hide":false,"instant":false,"interval":"","intervalFactor":2,"legendFormat":"{{job}} @ {{instance}}","metric":"","query":"avg(process_resident_memory_bytes{job=~\"$job\",instance=~\"$node\"}) by (job,instance)","refId":"","step":10,"target":""}],"timeFrom":null,"timeShift":null,"title":"Node Memory","transformations":[],"transparent":false,"type":"timeseries"},{"cacheTimeout":null,"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"description":"","editable":true,"error":false,"fieldConfig":{"defaults":{"color":{"mode":"palette-classic"},"custom":{"axisLabel":"","axisPlacement":"auto","axisSoftMax":null,"axisSoftMin":null,"barAlignment":0,"drawStyle":"line","fillOpacity":10,"gradientMode":"none","hideFrom":{"legend":false,"tooltip":false,"viz":false},"lineInterpolation":"linear","lineWidth":1,"pointSize":5,"scaleDistribution":{"log":2,"type":"linear"},"showPoints":"auto","spanNulls":false,"stacking":{},"thresholdsStyle":{"mode":"off"}},"decimals":null,"mappings":[],"max":null,"min":null,"thresholds":{"mode":"absolute","steps":[]},"unit":"bytes"},"overrides":[]},"gridPos":{"h":8,"w":12,"x":12,"y":0},"height":null,"hideTimeOverride":false,"id":20,"interval":"1s","links":[],"maxDataPoints":1000,"maxPerRow":null,"minSpan":null,"options":{"legend":{"calcs":[],"displayMode":"table","placement":"bottom"},"tooltip":{"mode":"single","sort":"none"}},"repeat":null,"repeatDirection":null,"span":null,"targets":[{"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"expr":"sum(state_store_meta_cache_size{job=~\"$job\",instance=~\"$node\"}) by (instance) + sum(state_store_block_cache_size{job=~\"$job\",instance=~\"$node\"}) by (instance) + sum(uploading_memory_size{job=~\"$job\",instance=~\"$node\"}) by (instance)","format":"time_series","hide":false,"instant":false,"interval":"","intervalFactor":2,"legendFormat":"storage @ {{instance}}","metric":"","query":"sum(state_store_meta_cache_size{job=~\"$job\",instance=~\"$node\"}) by (instance) + sum(state_store_block_cache_size{job=~\"$job\",instance=~\"$node\"}) by (instance) + sum(uploading_memory_size{job=~\"$job\",instance=~\"$node\"}) by (instance)","refId":"","step":10,"target":""}],"timeFrom":null,"timeShift":null,"title":"Memory Usage (Total)","transformations":[],"transparent":false,"type":"timeseries"},{"cacheTimeout":null,"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"description":"","editable":true,"error":false,"fieldConfig":{"defaults":{"color":{"mode":"palette-classic"},"custom":{"axisLabel":"","axisPlacement":"auto","axisSoftMax":null,"axisSoftMin":null,"barAlignment":0,"drawStyle":"line","fillOpacity":10,"gradientMode":"none","hideFrom":{"legend":false,"tooltip":false,"viz":false},"lineInterpolation":"linear","lineWidth":1,"pointSize":5,"scaleDistribution":{"log":2,"type":"linear"},"showPoints":"auto","spanNulls":false,"stacking":{},"thresholdsStyle":{"mode":"off"}},"decimals":null,"mappings":[],"max":null,"min":null,"thresholds":{"mode":"absolute","steps":[]},"unit":"bytes"},"overrides":[]},"gridPos":{"h":8,"w":12,"x":0,"y":8},"height":null,"hideTimeOverride":false,"id":21,"interval":"1s","links":[],"maxDataPoints":1000,"maxPerRow":null,"minSpan":null,"options":{"legend":{"calcs":["mean"],"displayMode":"table","placement":"bottom"},"tooltip":{"mode":"single","sort":"none"}},"repeat":null,"repeatDirection":null,"span":null,"targets":[{"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"expr":"rate(actor_memory_usage[$__rate_interval])","format":"time_series","hide":false,"instant":false,"interval":"","intervalFactor":2,"legendFormat":"streaming actor - {{actor_id}}","metric":"","query":"rate(actor_memory_usage[$__rate_interval])","refId":"","step":10,"target":""},{"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"expr":"sum(state_store_meta_cache_size{job=~\"$job\",instance=~\"$node\"}) by (job,instance)","format":"time_series","hide":false,"instant":false,"interval":"","intervalFactor":2,"legendFormat":"storage meta cache - {{job}} @ {{instance}}","metric":"","query":"sum(state_store_meta_cache_size{job=~\"$job\",instance=~\"$node\"}) by (job,instance)","refId":"","step":10,"target":""},{"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"expr":"sum(state_store_block_cache_size{job=~\"$job\",instance=~\"$node\"}) by (job,instance)","format":"time_series","hide":false,"instant":false,"interval":"","intervalFactor":2,"legendFormat":"storage block cache - {{job}} @ {{instance}}","metric":"","query":"sum(state_store_block_cache_size{job=~\"$job\",instance=~\"$node\"}) by (job,instance)","refId":"","step":10,"target":""},{"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"expr":"sum(uploading_memory_size{job=~\"$job\",instance=~\"$node\"}) by (job,instance)","format":"time_series","hide":false,"instant":false,"interval":"","intervalFactor":2,"legendFormat":"storage write buffer - {{job}} @ {{instance}}","metric":"","query":"sum(uploading_memory_size{job=~\"$job\",instance=~\"$node\"}) by (job,instance)","refId":"","step":10,"target":""},{"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"expr":"sum(stream_memory_usage{job=~\"$job\",instance=~\"$node\"} * on(table_id) group_left(materialized_view_id) table_info) by (materialized_view_id)","format":"time_series","hide":false,"instant":false,"interval":"","intervalFactor":2,"legendFormat":"materialized_view {{materialized_view_id}}","metric":"","query":"sum(stream_memory_usage{job=~\"$job\",instance=~\"$node\"} * on(table_id) group_left(materialized_view_id) table_info) by (materialized_view_id)","refId":"","step":10,"target":""}],"timeFrom":null,"timeShift":null,"title":"Memory Usage (Detailed)","transformations":[],"transparent":false,"type":"timeseries"},{"cacheTimeout":null,"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"description":"Executor cache statistics","editable":true,"error":false,"fieldConfig":{"defaults":{"color":{"mode":"palette-classic"},"custom":{"axisLabel":"","axisPlacement":"auto","axisSoftMax":null,"axisSoftMin":null,"barAlignment":0,"drawStyle":"line","fillOpacity":10,"gradientMode":"none","hideFrom":{"legend":false,"tooltip":false,"viz":false},"lineInterpolation":"linear","lineWidth":1,"pointSize":5,"scaleDistribution":{"log":2,"type":"linear"},"showPoints":"auto","spanNulls":false,"stacking":{},"thresholdsStyle":{"mode":"off"}},"decimals":null,"mappings":[],"max":null,"min":null,"thresholds":{"mode":"absolute","steps":[]},"unit":"ops"},"overrides":[]},"gridPos":{"h":8,"w":12,"x":12,"y":8},"height":null,"hideTimeOverride":false,"id":22,"interval":"1s","links":[],"maxDataPoints":1000,"maxPerRow":null,"minSpan":null,"options":{"legend":{"calcs":["mean"],"displayMode":"table","placement":"bottom"},"tooltip":{"mode":"single","sort":"none"}},"repeat":null,"repeatDirection":null,"span":null,"targets":[{"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"expr":"rate(stream_join_lookup_miss_count{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])","format":"time_series","hide":false,"instant":false,"interval":"","intervalFactor":2,"legendFormat":"Join - cache miss - {{side}} side, join_table_id {{join_table_id}} degree_table_id {{degree_table_id}} actor {{actor_id}}","metric":"","query":"rate(stream_join_lookup_miss_count{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])","refId":"","step":10,"target":""},{"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"expr":"rate(stream_join_lookup_total_count{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])","format":"time_series","hide":false,"instant":false,"interval":"","intervalFactor":2,"legendFormat":"Join - total lookups - {{side}} side, join_table_id {{join_table_id}} degree_table_id {{degree_table_id}} actor {{actor_id}}","metric":"","query":"rate(stream_join_lookup_total_count{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])","refId":"","step":10,"target":""},{"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"expr":"rate(stream_agg_lookup_miss_count{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])","format":"time_series","hide":false,"instant":false,"interval":"","intervalFactor":2,"legendFormat":"Agg - cache miss - table {{table_id}} actor {{actor_id}}","metric":"","query":"rate(stream_agg_lookup_miss_count{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])","refId":"","step":10,"target":""},{"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"expr":"rate(stream_agg_lookup_total_count{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])","format":"time_series","hide":false,"instant":false,"interval":"","intervalFactor":2,"legendFormat":"Agg - total lookups - table {{table_id}} actor {{actor_id}}","metric":"","query":"rate(stream_agg_lookup_total_count{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])","refId":"","step":10,"target":""},{"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"expr":"rate(stream_agg_distinct_cache_miss_count{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])","format":"time_series","hide":false,"instant":false,"interval":"","intervalFactor":2,"legendFormat":"Distinct agg - cache miss - table {{table_id}} actor {{actor_id}}","metric":"","query":"rate(stream_agg_distinct_cache_miss_count{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])","refId":"","step":10,"target":""},{"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"expr":"rate(stream_agg_distinct_total_cache_count{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])","format":"time_series","hide":false,"instant":false,"interval":"","intervalFactor":2,"legendFormat":"Distinct agg - total lookups - table {{table_id}} actor {{actor_id}}","metric":"","query":"rate(stream_agg_distinct_total_cache_count{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])","refId":"","step":10,"target":""},{"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"expr":"rate(stream_group_top_n_cache_miss_count{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])","format":"time_series","hide":false,"instant":false,"interval":"","intervalFactor":2,"legendFormat":"Group top n - cache miss - table {{table_id}} actor {{actor_id}}","metric":"","query":"rate(stream_group_top_n_cache_miss_count{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])","refId":"","step":10,"target":""},{"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"expr":"rate(stream_group_top_n_total_query_cache_count{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])","format":"time_series","hide":false,"instant":false,"interval":"","intervalFactor":2,"legendFormat":"Group top n - total lookups - table {{table_id}} actor {{actor_id}}","metric":"","query":"rate(stream_group_top_n_total_query_cache_count{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])","refId":"","step":10,"target":""},{"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"expr":"rate(stream_group_top_n_appendonly_cache_miss_count{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])","format":"time_series","hide":false,"instant":false,"interval":"","intervalFactor":2,"legendFormat":"Group top n appendonly - cache miss - table {{table_id}} actor {{actor_id}}","metric":"","query":"rate(stream_group_top_n_appendonly_cache_miss_count{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])","refId":"","step":10,"target":""},{"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"expr":"rate(stream_group_top_n_appendonly_total_query_cache_count{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])","format":"time_series","hide":false,"instant":false,"interval":"","intervalFactor":2,"legendFormat":"Group top n appendonly - total lookups - table {{table_id}} actor {{actor_id}}","metric":"","query":"rate(stream_group_top_n_appendonly_total_query_cache_count{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])","refId":"","step":10,"target":""},{"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"expr":"rate(stream_lookup_cache_miss_count{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])","format":"time_series","hide":false,"instant":false,"interval":"","intervalFactor":2,"legendFormat":"Lookup executor - cache miss - table {{table_id}} actor {{actor_id}}","metric":"","query":"rate(stream_lookup_cache_miss_count{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])","refId":"","step":10,"target":""},{"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"expr":"rate(stream_lookup_total_query_cache_count{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])","format":"time_series","hide":false,"instant":false,"interval":"","intervalFactor":2,"legendFormat":"Lookup executor - total lookups - table {{table_id}} actor {{actor_id}}","metric":"","query":"rate(stream_lookup_total_query_cache_count{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])","refId":"","step":10,"target":""},{"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"expr":"rate(stream_temporal_join_cache_miss_count{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])","format":"time_series","hide":false,"instant":false,"interval":"","intervalFactor":2,"legendFormat":"Temporal join - cache miss - table_id {{table_id}} actor {{actor_id}}","metric":"","query":"rate(stream_temporal_join_cache_miss_count{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])","refId":"","step":10,"target":""},{"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"expr":"rate(stream_temporal_join_total_query_cache_count{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])","format":"time_series","hide":false,"instant":false,"interval":"","intervalFactor":2,"legendFormat":"Temporal join - total lookups - table_id {{table_id}} actor {{actor_id}}","metric":"","query":"rate(stream_temporal_join_total_query_cache_count{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])","refId":"","step":10,"target":""},{"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"expr":"rate(stream_materialize_cache_hit_count{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])","format":"time_series","hide":false,"instant":false,"interval":"","intervalFactor":2,"legendFormat":"Materialize - cache hit count - table {{table_id}} - actor {{actor_id}} {{instance}}","metric":"","query":"rate(stream_materialize_cache_hit_count{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])","refId":"","step":10,"target":""},{"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"expr":"rate(stream_materialize_cache_total_count{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])","format":"time_series","hide":false,"instant":false,"interval":"","intervalFactor":2,"legendFormat":"Materialize - total cache count - table {{table_id}} - actor {{actor_id}} {{instance}}","metric":"","query":"rate(stream_materialize_cache_total_count{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])","refId":"","step":10,"target":""}],"timeFrom":null,"timeShift":null,"title":"Executor Cache","transformations":[],"transparent":false,"type":"timeseries"},{"cacheTimeout":null,"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"description":"","editable":true,"error":false,"fieldConfig":{"defaults":{"color":{"mode":"palette-classic"},"custom":{"axisLabel":"","axisPlacement":"auto","axisSoftMax":null,"axisSoftMin":null,"barAlignment":0,"drawStyle":"line","fillOpacity":10,"gradientMode":"none","hideFrom":{"legend":false,"tooltip":false,"viz":false},"lineInterpolation":"linear","lineWidth":1,"pointSize":5,"scaleDistribution":{"log":2,"type":"linear"},"showPoints":"auto","spanNulls":false,"stacking":{},"thresholdsStyle":{"mode":"off"}},"decimals":null,"mappings":[],"max":null,"min":null,"thresholds":{"mode":"absolute","steps":[]},"unit":"percentunit"},"overrides":[]},"gridPos":{"h":8,"w":12,"x":0,"y":16},"height":null,"hideTimeOverride":false,"id":23,"interval":"1s","links":[],"maxDataPoints":1000,"maxPerRow":null,"minSpan":null,"options":{"legend":{"calcs":["mean"],"displayMode":"table","placement":"bottom"},"tooltip":{"mode":"single","sort":"none"}},"repeat":null,"repeatDirection":null,"span":null,"targets":[{"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"expr":"(sum(rate(stream_join_lookup_miss_count{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])) by (side, join_table_id, degree_table_id, actor_id) ) / (sum(rate(stream_join_lookup_total_count{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])) by (side, join_table_id, degree_table_id, actor_id))","format":"time_series","hide":false,"instant":false,"interval":"","intervalFactor":2,"legendFormat":"join executor cache miss ratio - - {{side}} side, join_table_id {{join_table_id}} degree_table_id {{degree_table_id}} actor {{actor_id}}","metric":"","query":"(sum(rate(stream_join_lookup_miss_count{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])) by (side, join_table_id, degree_table_id, actor_id) ) / (sum(rate(stream_join_lookup_total_count{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])) by (side, join_table_id, degree_table_id, actor_id))","refId":"","step":10,"target":""},{"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"expr":"(sum(rate(stream_agg_lookup_miss_count{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])) by (table_id, actor_id) ) / (sum(rate(stream_agg_lookup_total_count{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])) by (table_id, actor_id))","format":"time_series","hide":false,"instant":false,"interval":"","intervalFactor":2,"legendFormat":"Agg cache miss ratio - table {{table_id}} actor {{actor_id}} ","metric":"","query":"(sum(rate(stream_agg_lookup_miss_count{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])) by (table_id, actor_id) ) / (sum(rate(stream_agg_lookup_total_count{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])) by (table_id, actor_id))","refId":"","step":10,"target":""},{"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"expr":"(sum(rate(stream_agg_distinct_cache_miss_count{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])) by (table_id, actor_id) ) / (sum(rate(stream_agg_distinct_total_cache_count{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])) by (table_id, actor_id))","format":"time_series","hide":false,"instant":false,"interval":"","intervalFactor":2,"legendFormat":"Distinct agg cache miss ratio - table {{table_id}} actor {{actor_id}} ","metric":"","query":"(sum(rate(stream_agg_distinct_cache_miss_count{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])) by (table_id, actor_id) ) / (sum(rate(stream_agg_distinct_total_cache_count{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])) by (table_id, actor_id))","refId":"","step":10,"target":""},{"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"expr":"(sum(rate(stream_group_top_n_cache_miss_count{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])) by (table_id, actor_id) ) / (sum(rate(stream_group_top_n_total_query_cache_count{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])) by (table_id, actor_id))","format":"time_series","hide":false,"instant":false,"interval":"","intervalFactor":2,"legendFormat":"Stream group top n cache miss ratio - table {{table_id}} actor {{actor_id}} ","metric":"","query":"(sum(rate(stream_group_top_n_cache_miss_count{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])) by (table_id, actor_id) ) / (sum(rate(stream_group_top_n_total_query_cache_count{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])) by (table_id, actor_id))","refId":"","step":10,"target":""},{"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"expr":"(sum(rate(stream_group_top_n_appendonly_cache_miss_count{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])) by (table_id, actor_id) ) / (sum(rate(stream_group_top_n_appendonly_total_query_cache_count{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])) by (table_id, actor_id))","format":"time_series","hide":false,"instant":false,"interval":"","intervalFactor":2,"legendFormat":"Stream group top n appendonly cache miss ratio - table {{table_id}} actor {{actor_id}} ","metric":"","query":"(sum(rate(stream_group_top_n_appendonly_cache_miss_count{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])) by (table_id, actor_id) ) / (sum(rate(stream_group_top_n_appendonly_total_query_cache_count{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])) by (table_id, actor_id))","refId":"","step":10,"target":""},{"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"expr":"(sum(rate(stream_lookup_cache_miss_count{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])) by (table_id, actor_id) ) / (sum(rate(stream_lookup_total_query_cache_count{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])) by (table_id, actor_id))","format":"time_series","hide":false,"instant":false,"interval":"","intervalFactor":2,"legendFormat":"Stream lookup cache miss ratio - table {{table_id}} actor {{actor_id}} ","metric":"","query":"(sum(rate(stream_lookup_cache_miss_count{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])) by (table_id, actor_id) ) / (sum(rate(stream_lookup_total_query_cache_count{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])) by (table_id, actor_id))","refId":"","step":10,"target":""},{"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"expr":"(sum(rate(stream_temporal_join_cache_miss_count{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])) by (table_id, actor_id) ) / (sum(rate(stream_temporal_join_total_query_cache_count{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])) by (table_id, actor_id))","format":"time_series","hide":false,"instant":false,"interval":"","intervalFactor":2,"legendFormat":"Stream temporal join cache miss ratio - table {{table_id}} actor {{actor_id}} ","metric":"","query":"(sum(rate(stream_temporal_join_cache_miss_count{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])) by (table_id, actor_id) ) / (sum(rate(stream_temporal_join_total_query_cache_count{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])) by (table_id, actor_id))","refId":"","step":10,"target":""},{"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"expr":"1 - (sum(rate(stream_materialize_cache_hit_count{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])) by (table_id, actor_id) ) / (sum(rate(stream_materialize_cache_total_count{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])) by (table_id, actor_id))","format":"time_series","hide":false,"instant":false,"interval":"","intervalFactor":2,"legendFormat":"materialize executor cache miss ratio - table {{table_id}} - actor {{actor_id}} {{instance}}","metric":"","query":"1 - (sum(rate(stream_materialize_cache_hit_count{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])) by (table_id, actor_id) ) / (sum(rate(stream_materialize_cache_total_count{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])) by (table_id, actor_id))","refId":"","step":10,"target":""}],"timeFrom":null,"timeShift":null,"title":"Executor Cache Miss Ratio","transformations":[],"transparent":false,"type":"timeseries"},{"cacheTimeout":null,"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"description":"Storage cache statistics","editable":true,"error":false,"fieldConfig":{"defaults":{"color":{"mode":"palette-classic"},"custom":{"axisLabel":"","axisPlacement":"auto","axisSoftMax":null,"axisSoftMin":null,"barAlignment":0,"drawStyle":"line","fillOpacity":10,"gradientMode":"none","hideFrom":{"legend":false,"tooltip":false,"viz":false},"lineInterpolation":"linear","lineWidth":1,"pointSize":5,"scaleDistribution":{"log":2,"type":"linear"},"showPoints":"auto","spanNulls":false,"stacking":{},"thresholdsStyle":{"mode":"off"}},"decimals":null,"mappings":[],"max":null,"min":null,"thresholds":{"mode":"absolute","steps":[]},"unit":"ops"},"overrides":[]},"gridPos":{"h":8,"w":12,"x":12,"y":16},"height":null,"hideTimeOverride":false,"id":24,"interval":"1s","links":[],"maxDataPoints":1000,"maxPerRow":null,"minSpan":null,"options":{"legend":{"calcs":["mean"],"displayMode":"table","placement":"bottom"},"tooltip":{"mode":"single","sort":"none"}},"repeat":null,"repeatDirection":null,"span":null,"targets":[{"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"expr":"sum(rate(state_store_sst_store_block_request_counts{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])) by (job, instance, table_id, type)","format":"time_series","hide":false,"instant":false,"interval":"","intervalFactor":2,"legendFormat":"memory cache - {{table_id}} @ {{type}} @ {{job}} @ {{instance}}","metric":"","query":"sum(rate(state_store_sst_store_block_request_counts{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])) by (job, instance, table_id, type)","refId":"","step":10,"target":""},{"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"expr":"sum(rate(state_store_sst_store_block_request_counts{type='meta_miss',job=~\"$job\",instance=~\"$node\"}[$__rate_interval])) by (job, type)","format":"time_series","hide":false,"instant":false,"interval":"","intervalFactor":2,"legendFormat":"total_meta_miss_count - {{job}} @ {{instance}}","metric":"","query":"sum(rate(state_store_sst_store_block_request_counts{type='meta_miss',job=~\"$job\",instance=~\"$node\"}[$__rate_interval])) by (job, type)","refId":"","step":10,"target":""}],"timeFrom":null,"timeShift":null,"title":"Storage Cache","transformations":[],"transparent":false,"type":"timeseries"},{"cacheTimeout":null,"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"description":"Storage bloom filter statistics","editable":true,"error":false,"fieldConfig":{"defaults":{"color":{"mode":"palette-classic"},"custom":{"axisLabel":"","axisPlacement":"auto","axisSoftMax":null,"axisSoftMin":null,"barAlignment":0,"drawStyle":"line","fillOpacity":10,"gradientMode":"none","hideFrom":{"legend":false,"tooltip":false,"viz":false},"lineInterpolation":"linear","lineWidth":1,"pointSize":5,"scaleDistribution":{"log":2,"type":"linear"},"showPoints":"auto","spanNulls":false,"stacking":{},"thresholdsStyle":{"mode":"off"}},"decimals":null,"mappings":[],"max":null,"min":null,"thresholds":{"mode":"absolute","steps":[]},"unit":"ops"},"overrides":[]},"gridPos":{"h":8,"w":12,"x":0,"y":24},"height":null,"hideTimeOverride":false,"id":25,"interval":"1s","links":[],"maxDataPoints":1000,"maxPerRow":null,"minSpan":null,"options":{"legend":{"calcs":["mean"],"displayMode":"table","placement":"bottom"},"tooltip":{"mode":"single","sort":"none"}},"repeat":null,"repeatDirection":null,"span":null,"targets":[{"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"expr":"sum(rate(state_store_read_req_check_bloom_filter_counts{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])) by (job,instance,table_id)","format":"time_series","hide":false,"instant":false,"interval":"","intervalFactor":2,"legendFormat":"bloom filter total - {{table_id}} @ {{job}} @ {{instance}}","metric":"","query":"sum(rate(state_store_read_req_check_bloom_filter_counts{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])) by (job,instance,table_id)","refId":"","step":10,"target":""},{"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"expr":"sum(rate(state_store_read_req_positive_but_non_exist_counts{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])) by (job,instance,table_id)","format":"time_series","hide":false,"instant":false,"interval":"","intervalFactor":2,"legendFormat":"bloom filter false positive - {{table_id}} @ {{job}} @ {{instance}}","metric":"","query":"sum(rate(state_store_read_req_positive_but_non_exist_counts{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])) by (job,instance,table_id)","refId":"","step":10,"target":""}],"timeFrom":null,"timeShift":null,"title":"Storage Bloom Filer","transformations":[],"transparent":false,"type":"timeseries"},{"cacheTimeout":null,"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"description":"Storage file cache statistics","editable":true,"error":false,"fieldConfig":{"defaults":{"color":{"mode":"palette-classic"},"custom":{"axisLabel":"","axisPlacement":"auto","axisSoftMax":null,"axisSoftMin":null,"barAlignment":0,"drawStyle":"line","fillOpacity":10,"gradientMode":"none","hideFrom":{"legend":false,"tooltip":false,"viz":false},"lineInterpolation":"linear","lineWidth":1,"pointSize":5,"scaleDistribution":{"log":2,"type":"linear"},"showPoints":"auto","spanNulls":false,"stacking":{},"thresholdsStyle":{"mode":"off"}},"decimals":null,"mappings":[],"max":null,"min":null,"thresholds":{"mode":"absolute","steps":[]},"unit":"ops"},"overrides":[]},"gridPos":{"h":8,"w":12,"x":12,"y":24},"height":null,"hideTimeOverride":false,"id":26,"interval":"1s","links":[],"maxDataPoints":1000,"maxPerRow":null,"minSpan":null,"options":{"legend":{"calcs":["mean"],"displayMode":"table","placement":"bottom"},"tooltip":{"mode":"single","sort":"none"}},"repeat":null,"repeatDirection":null,"span":null,"targets":[{"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"expr":"sum(rate(file_cache_latency_count{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])) by (op, instance)","format":"time_series","hide":false,"instant":false,"interval":"","intervalFactor":2,"legendFormat":"file cache {{op}} @ {{instance}}","metric":"","query":"sum(rate(file_cache_latency_count{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])) by (op, instance)","refId":"","step":10,"target":""},{"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"expr":"sum(rate(file_cache_miss{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])) by (instance)","format":"time_series","hide":false,"instant":false,"interval":"","intervalFactor":2,"legendFormat":"file cache miss @ {{instance}}","metric":"","query":"sum(rate(file_cache_miss{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])) by (instance)","refId":"","step":10,"target":""}],"timeFrom":null,"timeShift":null,"title":"Storage File Cache","transformations":[],"transparent":false,"type":"timeseries"}],"repeat":null,"repeatDirection":null,"span":null,"targets":[],"timeFrom":null,"timeShift":null,"title":"Memory","transformations":[],"transparent":false,"type":"row"},{"cacheTimeout":null,"collapsed":true,"datasource":null,"description":null,"editable":true,"error":false,"fieldConfig":{"defaults":{"thresholds":{"mode":"absolute","steps":[]}}},"gridPos":{"h":1,"w":24,"x":0,"y":44},"height":null,"hideTimeOverride":false,"id":27,"interval":null,"links":[],"maxDataPoints":100,"maxPerRow":null,"minSpan":null,"panels":[{"cacheTimeout":null,"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"description":"Send/Recv throughput per node for streaming exchange","editable":true,"error":false,"fieldConfig":{"defaults":{"color":{"mode":"palette-classic"},"custom":{"axisLabel":"","axisPlacement":"auto","axisSoftMax":null,"axisSoftMin":null,"barAlignment":0,"drawStyle":"line","fillOpacity":10,"gradientMode":"none","hideFrom":{"legend":false,"tooltip":false,"viz":false},"lineInterpolation":"linear","lineWidth":1,"pointSize":5,"scaleDistribution":{"log":2,"type":"linear"},"showPoints":"auto","spanNulls":false,"stacking":{},"thresholdsStyle":{"mode":"off"}},"decimals":null,"mappings":[],"max":null,"min":null,"thresholds":{"mode":"absolute","steps":[]},"unit":"Bps"},"overrides":[]},"gridPos":{"h":8,"w":12,"x":0,"y":0},"height":null,"hideTimeOverride":false,"id":28,"interval":"1s","links":[],"maxDataPoints":1000,"maxPerRow":null,"minSpan":null,"options":{"legend":{"calcs":["mean"],"displayMode":"table","placement":"bottom"},"tooltip":{"mode":"single","sort":"none"}},"repeat":null,"repeatDirection":null,"span":null,"targets":[{"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"expr":"sum(rate(stream_exchange_frag_send_size{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])) by (instance)","format":"time_series","hide":false,"instant":false,"interval":"","intervalFactor":2,"legendFormat":"Send @ {{instance}}","metric":"","query":"sum(rate(stream_exchange_frag_send_size{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])) by (instance)","refId":"","step":10,"target":""},{"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"expr":"sum(rate(stream_exchange_frag_recv_size{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])) by (instance)","format":"time_series","hide":false,"instant":false,"interval":"","intervalFactor":2,"legendFormat":"Recv @ {{instance}}","metric":"","query":"sum(rate(stream_exchange_frag_recv_size{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])) by (instance)","refId":"","step":10,"target":""}],"timeFrom":null,"timeShift":null,"title":"Streming Remote Exchange (Bytes/s)","transformations":[],"transparent":false,"type":"timeseries"},{"cacheTimeout":null,"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"description":"The remote storage read/write throughput per node","editable":true,"error":false,"fieldConfig":{"defaults":{"color":{"mode":"palette-classic"},"custom":{"axisLabel":"","axisPlacement":"auto","axisSoftMax":null,"axisSoftMin":null,"barAlignment":0,"drawStyle":"line","fillOpacity":10,"gradientMode":"none","hideFrom":{"legend":false,"tooltip":false,"viz":false},"lineInterpolation":"linear","lineWidth":1,"pointSize":5,"scaleDistribution":{"log":2,"type":"linear"},"showPoints":"auto","spanNulls":false,"stacking":{},"thresholdsStyle":{"mode":"off"}},"decimals":null,"mappings":[],"max":null,"min":null,"thresholds":{"mode":"absolute","steps":[]},"unit":"Bps"},"overrides":[]},"gridPos":{"h":8,"w":12,"x":12,"y":0},"height":null,"hideTimeOverride":false,"id":29,"interval":"1s","links":[],"maxDataPoints":1000,"maxPerRow":null,"minSpan":null,"options":{"legend":{"calcs":["mean"],"displayMode":"table","placement":"bottom"},"tooltip":{"mode":"single","sort":"none"}},"repeat":null,"repeatDirection":null,"span":null,"targets":[{"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"expr":"sum(rate(object_store_read_bytes{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])) by (instance)","format":"time_series","hide":false,"instant":false,"interval":"","intervalFactor":2,"legendFormat":"read - {{instance}}","metric":"","query":"sum(rate(object_store_read_bytes{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])) by (instance)","refId":"","step":10,"target":""},{"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"expr":"sum(rate(object_store_write_bytes{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])) by (instance)","format":"time_series","hide":false,"instant":false,"interval":"","intervalFactor":2,"legendFormat":"write - {{instance}}","metric":"","query":"sum(rate(object_store_write_bytes{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])) by (instance)","refId":"","step":10,"target":""}],"timeFrom":null,"timeShift":null,"title":"Storage Remote I/O (Bytes/s)","transformations":[],"transparent":false,"type":"timeseries"},{"cacheTimeout":null,"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"description":"","editable":true,"error":false,"fieldConfig":{"defaults":{"color":{"mode":"palette-classic"},"custom":{"axisLabel":"","axisPlacement":"auto","axisSoftMax":null,"axisSoftMin":null,"barAlignment":0,"drawStyle":"line","fillOpacity":10,"gradientMode":"none","hideFrom":{"legend":false,"tooltip":false,"viz":false},"lineInterpolation":"linear","lineWidth":1,"pointSize":5,"scaleDistribution":{"log":2,"type":"linear"},"showPoints":"auto","spanNulls":false,"stacking":{},"thresholdsStyle":{"mode":"off"}},"decimals":null,"mappings":[],"max":null,"min":null,"thresholds":{"mode":"absolute","steps":[]},"unit":"row"},"overrides":[]},"gridPos":{"h":8,"w":12,"x":0,"y":8},"height":null,"hideTimeOverride":false,"id":30,"interval":"1s","links":[],"maxDataPoints":1000,"maxPerRow":null,"minSpan":null,"options":{"legend":{"calcs":["mean"],"displayMode":"table","placement":"bottom"},"tooltip":{"mode":"single","sort":"none"}},"repeat":null,"repeatDirection":null,"span":null,"targets":[{"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"expr":"batch_exchange_recv_row_number{job=~\"$job\",instance=~\"$node\"}","format":"time_series","hide":false,"instant":false,"interval":"","intervalFactor":2,"legendFormat":"{{query_id}} : {{source_stage_id}}.{{source_task_id}} -> {{target_stage_id}}.{{target_task_id}}","metric":"","query":"batch_exchange_recv_row_number{job=~\"$job\",instance=~\"$node\"}","refId":"","step":10,"target":""}],"timeFrom":null,"timeShift":null,"title":"Batch Exchange Recv (Rows/s)","transformations":[],"transparent":false,"type":"timeseries"}],"repeat":null,"repeatDirection":null,"span":null,"targets":[],"timeFrom":null,"timeShift":null,"title":"Network","transformations":[],"transparent":false,"type":"row"},{"cacheTimeout":null,"collapsed":true,"datasource":null,"description":null,"editable":true,"error":false,"fieldConfig":{"defaults":{"thresholds":{"mode":"absolute","steps":[]}}},"gridPos":{"h":1,"w":24,"x":0,"y":45},"height":null,"hideTimeOverride":false,"id":31,"interval":null,"links":[],"maxDataPoints":100,"maxPerRow":null,"minSpan":null,"panels":[{"cacheTimeout":null,"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"description":"\n Objects are classified into 3 groups:\n - not referenced by versions: these object are being deleted from object store.\n - referenced by non-current versions: these objects are stale (not in the latest version), but those old versions may still be in use (e.g. long-running pinning). Thus those objects cannot be deleted at the moment.\n - referenced by current version: these objects are in the latest version.\n ","editable":true,"error":false,"fieldConfig":{"defaults":{"color":{"mode":"palette-classic"},"custom":{"axisLabel":"","axisPlacement":"auto","axisSoftMax":null,"axisSoftMin":null,"barAlignment":0,"drawStyle":"line","fillOpacity":10,"gradientMode":"none","hideFrom":{"legend":false,"tooltip":false,"viz":false},"lineInterpolation":"linear","lineWidth":1,"pointSize":5,"scaleDistribution":{"log":2,"type":"linear"},"showPoints":"auto","spanNulls":false,"stacking":{},"thresholdsStyle":{"mode":"off"}},"decimals":null,"mappings":[],"max":null,"min":null,"thresholds":{"mode":"absolute","steps":[]},"unit":"bytes"},"overrides":[]},"gridPos":{"h":8,"w":12,"x":0,"y":0},"height":null,"hideTimeOverride":false,"id":32,"interval":"1s","links":[],"maxDataPoints":1000,"maxPerRow":null,"minSpan":null,"options":{"legend":{"calcs":["mean"],"displayMode":"table","placement":"bottom"},"tooltip":{"mode":"single","sort":"none"}},"repeat":null,"repeatDirection":null,"span":null,"targets":[{"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"expr":"storage_stale_object_size{job=~\"$job\",instance=~\"$node\"}","format":"time_series","hide":false,"instant":false,"interval":"","intervalFactor":2,"legendFormat":"not referenced by versions","metric":"","query":"storage_stale_object_size{job=~\"$job\",instance=~\"$node\"}","refId":"","step":10,"target":""},{"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"expr":"storage_old_version_object_size{job=~\"$job\",instance=~\"$node\"}","format":"time_series","hide":false,"instant":false,"interval":"","intervalFactor":2,"legendFormat":"referenced by non-current versions","metric":"","query":"storage_old_version_object_size{job=~\"$job\",instance=~\"$node\"}","refId":"","step":10,"target":""},{"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"expr":"storage_current_version_object_size{job=~\"$job\",instance=~\"$node\"}","format":"time_series","hide":false,"instant":false,"interval":"","intervalFactor":2,"legendFormat":"referenced by current version","metric":"","query":"storage_current_version_object_size{job=~\"$job\",instance=~\"$node\"}","refId":"","step":10,"target":""}],"timeFrom":null,"timeShift":null,"title":"Object Size","transformations":[],"transparent":false,"type":"timeseries"},{"cacheTimeout":null,"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"description":"The storage size of each materialized view","editable":true,"error":false,"fieldConfig":{"defaults":{"color":{"mode":"palette-classic"},"custom":{"axisLabel":"","axisPlacement":"auto","axisSoftMax":null,"axisSoftMin":null,"barAlignment":0,"drawStyle":"line","fillOpacity":10,"gradientMode":"none","hideFrom":{"legend":false,"tooltip":false,"viz":false},"lineInterpolation":"linear","lineWidth":1,"pointSize":5,"scaleDistribution":{"log":2,"type":"linear"},"showPoints":"auto","spanNulls":false,"stacking":{},"thresholdsStyle":{"mode":"off"}},"decimals":null,"mappings":[],"max":null,"min":null,"thresholds":{"mode":"absolute","steps":[]},"unit":"kbytes"},"overrides":[]},"gridPos":{"h":8,"w":12,"x":12,"y":0},"height":null,"hideTimeOverride":false,"id":33,"interval":"1s","links":[],"maxDataPoints":1000,"maxPerRow":null,"minSpan":null,"options":{"legend":{"calcs":["mean"],"displayMode":"table","placement":"bottom"},"tooltip":{"mode":"single","sort":"none"}},"repeat":null,"repeatDirection":null,"span":null,"targets":[{"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"expr":"storage_materialized_view_stats{metric='materialized_view_total_size',job=~\"$job\",instance=~\"$node\"}/1024","format":"time_series","hide":false,"instant":false,"interval":"","intervalFactor":2,"legendFormat":"{{metric}}, mv id - {{table_id}} ","metric":"","query":"storage_materialized_view_stats{metric='materialized_view_total_size',job=~\"$job\",instance=~\"$node\"}/1024","refId":"","step":10,"target":""}],"timeFrom":null,"timeShift":null,"title":"Materialized View Size","transformations":[],"transparent":false,"type":"timeseries"},{"cacheTimeout":null,"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"description":"\n Objects are classified into 3 groups:\n - not referenced by versions: these object are being deleted from object store.\n - referenced by non-current versions: these objects are stale (not in the latest version), but those old versions may still be in use (e.g. long-running pinning). Thus those objects cannot be deleted at the moment.\n - referenced by current version: these objects are in the latest version.\n ","editable":true,"error":false,"fieldConfig":{"defaults":{"color":{"mode":"palette-classic"},"custom":{"axisLabel":"","axisPlacement":"auto","axisSoftMax":null,"axisSoftMin":null,"barAlignment":0,"drawStyle":"line","fillOpacity":10,"gradientMode":"none","hideFrom":{"legend":false,"tooltip":false,"viz":false},"lineInterpolation":"linear","lineWidth":1,"pointSize":5,"scaleDistribution":{"log":2,"type":"linear"},"showPoints":"auto","spanNulls":false,"stacking":{},"thresholdsStyle":{"mode":"off"}},"decimals":null,"mappings":[],"max":null,"min":null,"thresholds":{"mode":"absolute","steps":[]},"unit":""},"overrides":[]},"gridPos":{"h":8,"w":12,"x":0,"y":8},"height":null,"hideTimeOverride":false,"id":34,"interval":"1s","links":[],"maxDataPoints":1000,"maxPerRow":null,"minSpan":null,"options":{"legend":{"calcs":["mean"],"displayMode":"table","placement":"bottom"},"tooltip":{"mode":"single","sort":"none"}},"repeat":null,"repeatDirection":null,"span":null,"targets":[{"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"expr":"storage_stale_object_count{job=~\"$job\",instance=~\"$node\"}","format":"time_series","hide":false,"instant":false,"interval":"","intervalFactor":2,"legendFormat":"not referenced by versions","metric":"","query":"storage_stale_object_count{job=~\"$job\",instance=~\"$node\"}","refId":"","step":10,"target":""},{"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"expr":"storage_old_version_object_count{job=~\"$job\",instance=~\"$node\"}","format":"time_series","hide":false,"instant":false,"interval":"","intervalFactor":2,"legendFormat":"referenced by non-current versions","metric":"","query":"storage_old_version_object_count{job=~\"$job\",instance=~\"$node\"}","refId":"","step":10,"target":""},{"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"expr":"storage_current_version_object_count{job=~\"$job\",instance=~\"$node\"}","format":"time_series","hide":false,"instant":false,"interval":"","intervalFactor":2,"legendFormat":"referenced by current version","metric":"","query":"storage_current_version_object_count{job=~\"$job\",instance=~\"$node\"}","refId":"","step":10,"target":""}],"timeFrom":null,"timeShift":null,"title":"Object Total Number","transformations":[],"transparent":false,"type":"timeseries"},{"cacheTimeout":null,"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"description":"The number of bytes that have been written by compaction.Flush refers to the process of compacting Memtables to SSTables at Level 0.Compaction refers to the process of compacting SSTables at one level to another level.","editable":true,"error":false,"fieldConfig":{"defaults":{"color":{"mode":"palette-classic"},"custom":{"axisLabel":"","axisPlacement":"auto","axisSoftMax":null,"axisSoftMin":null,"barAlignment":0,"drawStyle":"line","fillOpacity":10,"gradientMode":"none","hideFrom":{"legend":false,"tooltip":false,"viz":false},"lineInterpolation":"linear","lineWidth":1,"pointSize":5,"scaleDistribution":{"log":2,"type":"linear"},"showPoints":"auto","spanNulls":false,"stacking":{},"thresholdsStyle":{"mode":"off"}},"decimals":null,"mappings":[],"max":null,"min":null,"thresholds":{"mode":"absolute","steps":[]},"unit":"bytes"},"overrides":[]},"gridPos":{"h":8,"w":12,"x":12,"y":8},"height":null,"hideTimeOverride":false,"id":35,"interval":"1s","links":[],"maxDataPoints":1000,"maxPerRow":null,"minSpan":null,"options":{"legend":{"calcs":["mean"],"displayMode":"table","placement":"bottom"},"tooltip":{"mode":"single","sort":"none"}},"repeat":null,"repeatDirection":null,"span":null,"targets":[{"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"expr":"sum(storage_level_compact_write{job=~\"$job\",instance=~\"$node\"}) by (job) > 0","format":"time_series","hide":false,"instant":false,"interval":"","intervalFactor":2,"legendFormat":"Compaction - {{job}}","metric":"","query":"sum(storage_level_compact_write{job=~\"$job\",instance=~\"$node\"}) by (job) > 0","refId":"","step":10,"target":""},{"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"expr":"sum(compactor_write_build_l0_bytes{job=~\"$job\",instance=~\"$node\"}) by (job) > 0","format":"time_series","hide":false,"instant":false,"interval":"","intervalFactor":2,"legendFormat":"Flush - {{job}}","metric":"","query":"sum(compactor_write_build_l0_bytes{job=~\"$job\",instance=~\"$node\"}) by (job) > 0","refId":"","step":10,"target":""}],"timeFrom":null,"timeShift":null,"title":"Write Bytes","transformations":[],"transparent":false,"type":"timeseries"},{"cacheTimeout":null,"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"description":"The remote storage read/write throughput","editable":true,"error":false,"fieldConfig":{"defaults":{"color":{"mode":"palette-classic"},"custom":{"axisLabel":"","axisPlacement":"auto","axisSoftMax":null,"axisSoftMin":null,"barAlignment":0,"drawStyle":"line","fillOpacity":10,"gradientMode":"none","hideFrom":{"legend":false,"tooltip":false,"viz":false},"lineInterpolation":"linear","lineWidth":1,"pointSize":5,"scaleDistribution":{"log":2,"type":"linear"},"showPoints":"auto","spanNulls":false,"stacking":{},"thresholdsStyle":{"mode":"off"}},"decimals":null,"mappings":[],"max":null,"min":null,"thresholds":{"mode":"absolute","steps":[]},"unit":"Bps"},"overrides":[]},"gridPos":{"h":8,"w":12,"x":0,"y":16},"height":null,"hideTimeOverride":false,"id":36,"interval":"1s","links":[],"maxDataPoints":1000,"maxPerRow":null,"minSpan":null,"options":{"legend":{"calcs":["mean"],"displayMode":"table","placement":"bottom"},"tooltip":{"mode":"single","sort":"none"}},"repeat":null,"repeatDirection":null,"span":null,"targets":[{"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"expr":"sum(rate(object_store_read_bytes{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])) by (job)","format":"time_series","hide":false,"instant":false,"interval":"","intervalFactor":2,"legendFormat":"read - {{job}}","metric":"","query":"sum(rate(object_store_read_bytes{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])) by (job)","refId":"","step":10,"target":""},{"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"expr":"sum(rate(object_store_write_bytes{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])) by (job)","format":"time_series","hide":false,"instant":false,"interval":"","intervalFactor":2,"legendFormat":"write - {{job}}","metric":"","query":"sum(rate(object_store_write_bytes{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])) by (job)","refId":"","step":10,"target":""}],"timeFrom":null,"timeShift":null,"title":"Storage Remote I/O (Bytes/s)","transformations":[],"transparent":false,"type":"timeseries"},{"cacheTimeout":null,"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"description":"Size statistics for checkpoint","editable":true,"error":false,"fieldConfig":{"defaults":{"color":{"mode":"palette-classic"},"custom":{"axisLabel":"","axisPlacement":"auto","axisSoftMax":null,"axisSoftMin":null,"barAlignment":0,"drawStyle":"line","fillOpacity":10,"gradientMode":"none","hideFrom":{"legend":false,"tooltip":false,"viz":false},"lineInterpolation":"linear","lineWidth":1,"pointSize":5,"scaleDistribution":{"log":2,"type":"linear"},"showPoints":"auto","spanNulls":false,"stacking":{},"thresholdsStyle":{"mode":"off"}},"decimals":null,"mappings":[],"max":null,"min":null,"thresholds":{"mode":"absolute","steps":[]},"unit":"bytes"},"overrides":[]},"gridPos":{"h":8,"w":12,"x":12,"y":16},"height":null,"hideTimeOverride":false,"id":37,"interval":"1s","links":[],"maxDataPoints":1000,"maxPerRow":null,"minSpan":null,"options":{"legend":{"calcs":["mean"],"displayMode":"table","placement":"bottom"},"tooltip":{"mode":"single","sort":"none"}},"repeat":null,"repeatDirection":null,"span":null,"targets":[{"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"expr":"histogram_quantile(0.5, sum(rate(state_store_sync_size_bucket{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])) by (le, job))","format":"time_series","hide":false,"instant":false,"interval":"","intervalFactor":2,"legendFormat":"p50 - {{job}}","metric":"","query":"histogram_quantile(0.5, sum(rate(state_store_sync_size_bucket{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])) by (le, job))","refId":"","step":10,"target":""},{"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"expr":"histogram_quantile(0.99, sum(rate(state_store_sync_size_bucket{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])) by (le, job))","format":"time_series","hide":false,"instant":false,"interval":"","intervalFactor":2,"legendFormat":"p99 - {{job}}","metric":"","query":"histogram_quantile(0.99, sum(rate(state_store_sync_size_bucket{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])) by (le, job))","refId":"","step":10,"target":""},{"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"expr":"sum by(le, job) (rate(state_store_sync_size_sum{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])) / sum by(le, job) (rate(state_store_sync_size_count{job=~\"$job\",instance=~\"$node\"}[$__rate_interval]))","format":"time_series","hide":false,"instant":false,"interval":"","intervalFactor":2,"legendFormat":"avg - {{job}}","metric":"","query":"sum by(le, job) (rate(state_store_sync_size_sum{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])) / sum by(le, job) (rate(state_store_sync_size_count{job=~\"$job\",instance=~\"$node\"}[$__rate_interval]))","refId":"","step":10,"target":""}],"timeFrom":null,"timeShift":null,"title":"Checkpoint Size","transformations":[],"transparent":false,"type":"timeseries"}],"repeat":null,"repeatDirection":null,"span":null,"targets":[],"timeFrom":null,"timeShift":null,"title":"Storage","transformations":[],"transparent":false,"type":"row"},{"cacheTimeout":null,"collapsed":true,"datasource":null,"description":null,"editable":true,"error":false,"fieldConfig":{"defaults":{"thresholds":{"mode":"absolute","steps":[]}}},"gridPos":{"h":1,"w":24,"x":0,"y":46},"height":null,"hideTimeOverride":false,"id":38,"interval":null,"links":[],"maxDataPoints":100,"maxPerRow":null,"minSpan":null,"panels":[{"cacheTimeout":null,"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"description":"The figure shows the number of rows read by each source per second.","editable":true,"error":false,"fieldConfig":{"defaults":{"color":{"mode":"palette-classic"},"custom":{"axisLabel":"","axisPlacement":"auto","axisSoftMax":null,"axisSoftMin":null,"barAlignment":0,"drawStyle":"line","fillOpacity":10,"gradientMode":"none","hideFrom":{"legend":false,"tooltip":false,"viz":false},"lineInterpolation":"linear","lineWidth":1,"pointSize":5,"scaleDistribution":{"log":2,"type":"linear"},"showPoints":"auto","spanNulls":false,"stacking":{},"thresholdsStyle":{"mode":"off"}},"decimals":null,"mappings":[],"max":null,"min":null,"thresholds":{"mode":"absolute","steps":[]},"unit":"rows/s"},"overrides":[]},"gridPos":{"h":8,"w":12,"x":0,"y":0},"height":null,"hideTimeOverride":false,"id":39,"interval":"1s","links":[],"maxDataPoints":1000,"maxPerRow":null,"minSpan":null,"options":{"legend":{"calcs":["mean"],"displayMode":"table","placement":"bottom"},"tooltip":{"mode":"single","sort":"none"}},"repeat":null,"repeatDirection":null,"span":null,"targets":[{"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"expr":"rate(stream_source_output_rows_counts{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])","format":"time_series","hide":false,"instant":false,"interval":"","intervalFactor":2,"legendFormat":"source={{source_name}} actor={{actor_id}} @ {{instance}}","metric":"","query":"rate(stream_source_output_rows_counts{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])","refId":"","step":10,"target":""}],"timeFrom":null,"timeShift":null,"title":"Source Throughput(rows/s)","transformations":[],"transparent":false,"type":"timeseries"},{"cacheTimeout":null,"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"description":"The figure shows the number of bytes read by each source per second.","editable":true,"error":false,"fieldConfig":{"defaults":{"color":{"mode":"palette-classic"},"custom":{"axisLabel":"","axisPlacement":"auto","axisSoftMax":null,"axisSoftMin":null,"barAlignment":0,"drawStyle":"line","fillOpacity":10,"gradientMode":"none","hideFrom":{"legend":false,"tooltip":false,"viz":false},"lineInterpolation":"linear","lineWidth":1,"pointSize":5,"scaleDistribution":{"log":2,"type":"linear"},"showPoints":"auto","spanNulls":false,"stacking":{},"thresholdsStyle":{"mode":"off"}},"decimals":null,"mappings":[],"max":null,"min":null,"thresholds":{"mode":"absolute","steps":[]},"unit":"MB/s"},"overrides":[]},"gridPos":{"h":8,"w":12,"x":12,"y":0},"height":null,"hideTimeOverride":false,"id":40,"interval":"1s","links":[],"maxDataPoints":1000,"maxPerRow":null,"minSpan":null,"options":{"legend":{"calcs":["mean"],"displayMode":"table","placement":"bottom"},"tooltip":{"mode":"single","sort":"none"}},"repeat":null,"repeatDirection":null,"span":null,"targets":[{"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"expr":"(sum by (source_id)(rate(partition_input_bytes{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])))/(1000*1000)","format":"time_series","hide":false,"instant":false,"interval":"","intervalFactor":2,"legendFormat":"source={{source_id}}","metric":"","query":"(sum by (source_id)(rate(partition_input_bytes{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])))/(1000*1000)","refId":"","step":10,"target":""}],"timeFrom":null,"timeShift":null,"title":"Source Throughput(MB/s)","transformations":[],"transparent":false,"type":"timeseries"},{"cacheTimeout":null,"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"description":"The figure shows the number of rows written into each materialized executor actor per second.","editable":true,"error":false,"fieldConfig":{"defaults":{"color":{"mode":"palette-classic"},"custom":{"axisLabel":"","axisPlacement":"auto","axisSoftMax":null,"axisSoftMin":null,"barAlignment":0,"drawStyle":"line","fillOpacity":10,"gradientMode":"none","hideFrom":{"legend":false,"tooltip":false,"viz":false},"lineInterpolation":"linear","lineWidth":1,"pointSize":5,"scaleDistribution":{"log":2,"type":"linear"},"showPoints":"auto","spanNulls":false,"stacking":{},"thresholdsStyle":{"mode":"off"}},"decimals":null,"mappings":[],"max":null,"min":null,"thresholds":{"mode":"absolute","steps":[]},"unit":"rows/s"},"overrides":[]},"gridPos":{"h":8,"w":12,"x":0,"y":8},"height":null,"hideTimeOverride":false,"id":41,"interval":"1s","links":[],"maxDataPoints":1000,"maxPerRow":null,"minSpan":null,"options":{"legend":{"calcs":["mean"],"displayMode":"table","placement":"bottom"},"tooltip":{"mode":"single","sort":"none"}},"repeat":null,"repeatDirection":null,"span":null,"targets":[{"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"expr":"sum(rate(stream_executor_row_count{executor_identity=~\".*MaterializeExecutor.*\",job=~\"$job\",instance=~\"$node\"}[$__rate_interval]) * on(actor_id) group_left(materialized_view_id, table_name) (group(table_info{table_type=~\"MATERIALIZED_VIEW\",job=~\"$job\",instance=~\"$node\"}) by (actor_id, materialized_view_id, table_name))) by (materialized_view_id, table_name)","format":"time_series","hide":false,"instant":false,"interval":"","intervalFactor":2,"legendFormat":"materialized view {{table_name}} table_id {{materialized_view_id}}","metric":"","query":"sum(rate(stream_executor_row_count{executor_identity=~\".*MaterializeExecutor.*\",job=~\"$job\",instance=~\"$node\"}[$__rate_interval]) * on(actor_id) group_left(materialized_view_id, table_name) (group(table_info{table_type=~\"MATERIALIZED_VIEW\",job=~\"$job\",instance=~\"$node\"}) by (actor_id, materialized_view_id, table_name))) by (materialized_view_id, table_name)","refId":"","step":10,"target":""}],"timeFrom":null,"timeShift":null,"title":"Materialized View Throughput(rows/s)","transformations":[],"transparent":false,"type":"timeseries"},{"cacheTimeout":null,"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"description":"Total number of rows that have been read from the backfill operator used by MV on MV","editable":true,"error":false,"fieldConfig":{"defaults":{"color":{"mode":"palette-classic"},"custom":{"axisLabel":"","axisPlacement":"auto","axisSoftMax":null,"axisSoftMin":null,"barAlignment":0,"drawStyle":"line","fillOpacity":10,"gradientMode":"none","hideFrom":{"legend":false,"tooltip":false,"viz":false},"lineInterpolation":"linear","lineWidth":1,"pointSize":5,"scaleDistribution":{"log":2,"type":"linear"},"showPoints":"auto","spanNulls":false,"stacking":{},"thresholdsStyle":{"mode":"off"}},"decimals":null,"mappings":[],"max":null,"min":null,"thresholds":{"mode":"absolute","steps":[]},"unit":"rows/s"},"overrides":[]},"gridPos":{"h":8,"w":12,"x":12,"y":8},"height":null,"hideTimeOverride":false,"id":42,"interval":"1s","links":[],"maxDataPoints":1000,"maxPerRow":null,"minSpan":null,"options":{"legend":{"calcs":["mean"],"displayMode":"table","placement":"bottom"},"tooltip":{"mode":"single","sort":"none"}},"repeat":null,"repeatDirection":null,"span":null,"targets":[{"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"expr":"rate(stream_backfill_snapshot_read_row_count{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])","format":"time_series","hide":false,"instant":false,"interval":"","intervalFactor":2,"legendFormat":"Read Snapshot - table_id={{table_id}} actor={{actor_id}} @ {{instance}}","metric":"","query":"rate(stream_backfill_snapshot_read_row_count{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])","refId":"","step":10,"target":""},{"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"expr":"rate(stream_backfill_upstream_output_row_count{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])","format":"time_series","hide":false,"instant":false,"interval":"","intervalFactor":2,"legendFormat":"Upstream - table_id={{table_id}} actor={{actor_id}} @ {{instance}}","metric":"","query":"rate(stream_backfill_upstream_output_row_count{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])","refId":"","step":10,"target":""}],"timeFrom":null,"timeShift":null,"title":"Backfill Throughput(rows)","transformations":[],"transparent":false,"type":"timeseries"},{"cacheTimeout":null,"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"description":"We first record the total blocking duration(ns) of output buffer of each actor. It shows how much time it takes an actor to process a message, i.e. a barrier, a watermark or rows of data, on average. Then we divide this duration by 1 second and show it as a percentage.","editable":true,"error":false,"fieldConfig":{"defaults":{"color":{"mode":"palette-classic"},"custom":{"axisLabel":"","axisPlacement":"auto","axisSoftMax":null,"axisSoftMin":null,"barAlignment":0,"drawStyle":"line","fillOpacity":10,"gradientMode":"none","hideFrom":{"legend":false,"tooltip":false,"viz":false},"lineInterpolation":"linear","lineWidth":1,"pointSize":5,"scaleDistribution":{"log":2,"type":"linear"},"showPoints":"auto","spanNulls":false,"stacking":{},"thresholdsStyle":{"mode":"off"}},"decimals":null,"mappings":[],"max":null,"min":null,"thresholds":{"mode":"absolute","steps":[]},"unit":"percentunit"},"overrides":[]},"gridPos":{"h":8,"w":12,"x":0,"y":16},"height":null,"hideTimeOverride":false,"id":43,"interval":"1s","links":[],"maxDataPoints":1000,"maxPerRow":null,"minSpan":null,"options":{"legend":{"calcs":["mean"],"displayMode":"table","placement":"bottom"},"tooltip":{"mode":"single","sort":"none"}},"repeat":null,"repeatDirection":null,"span":null,"targets":[{"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"expr":"avg(rate(stream_actor_output_buffer_blocking_duration_ns{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])) by (fragment_id, downstream_fragment_id) / 1000000000","format":"time_series","hide":false,"instant":false,"interval":"","intervalFactor":2,"legendFormat":"fragment {{fragment_id}}->{{downstream_fragment_id}}","metric":"","query":"avg(rate(stream_actor_output_buffer_blocking_duration_ns{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])) by (fragment_id, downstream_fragment_id) / 1000000000","refId":"","step":10,"target":""}],"timeFrom":null,"timeShift":null,"title":"Actor Output Blocking Time Ratio (Backpressure)","transformations":[],"transparent":false,"type":"timeseries"}],"repeat":null,"repeatDirection":null,"span":null,"targets":[],"timeFrom":null,"timeShift":null,"title":"Streaming","transformations":[],"transparent":false,"type":"row"},{"cacheTimeout":null,"collapsed":true,"datasource":null,"description":null,"editable":true,"error":false,"fieldConfig":{"defaults":{"thresholds":{"mode":"absolute","steps":[]}}},"gridPos":{"h":1,"w":24,"x":0,"y":47},"height":null,"hideTimeOverride":false,"id":44,"interval":null,"links":[],"maxDataPoints":100,"maxPerRow":null,"minSpan":null,"panels":[{"cacheTimeout":null,"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"description":"","editable":true,"error":false,"fieldConfig":{"defaults":{"color":{"mode":"palette-classic"},"custom":{"axisLabel":"","axisPlacement":"auto","axisSoftMax":null,"axisSoftMin":null,"barAlignment":0,"drawStyle":"line","fillOpacity":10,"gradientMode":"none","hideFrom":{"legend":false,"tooltip":false,"viz":false},"lineInterpolation":"linear","lineWidth":1,"pointSize":5,"scaleDistribution":{"log":2,"type":"linear"},"showPoints":"auto","spanNulls":false,"stacking":{},"thresholdsStyle":{"mode":"off"}},"decimals":null,"mappings":[],"max":null,"min":null,"thresholds":{"mode":"absolute","steps":[]},"unit":""},"overrides":[]},"gridPos":{"h":8,"w":12,"x":0,"y":0},"height":null,"hideTimeOverride":false,"id":45,"interval":"1s","links":[],"maxDataPoints":1000,"maxPerRow":null,"minSpan":null,"options":{"legend":{"calcs":["last"],"displayMode":"table","placement":"bottom"},"tooltip":{"mode":"single","sort":"none"}},"repeat":null,"repeatDirection":null,"span":null,"targets":[{"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"expr":"distributed_running_query_num{job=~\"$job\",instance=~\"$node\"}","format":"time_series","hide":false,"instant":false,"interval":"","intervalFactor":2,"legendFormat":"The number of running query in distributed execution mode","metric":"","query":"distributed_running_query_num{job=~\"$job\",instance=~\"$node\"}","refId":"","step":10,"target":""}],"timeFrom":null,"timeShift":null,"title":"Running query in distributed execution mode","transformations":[],"transparent":false,"type":"timeseries"},{"cacheTimeout":null,"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"description":"","editable":true,"error":false,"fieldConfig":{"defaults":{"color":{"mode":"palette-classic"},"custom":{"axisLabel":"","axisPlacement":"auto","axisSoftMax":null,"axisSoftMin":null,"barAlignment":0,"drawStyle":"line","fillOpacity":10,"gradientMode":"none","hideFrom":{"legend":false,"tooltip":false,"viz":false},"lineInterpolation":"linear","lineWidth":1,"pointSize":5,"scaleDistribution":{"log":2,"type":"linear"},"showPoints":"auto","spanNulls":false,"stacking":{},"thresholdsStyle":{"mode":"off"}},"decimals":null,"mappings":[],"max":null,"min":null,"thresholds":{"mode":"absolute","steps":[]},"unit":""},"overrides":[]},"gridPos":{"h":8,"w":12,"x":12,"y":0},"height":null,"hideTimeOverride":false,"id":46,"interval":"1s","links":[],"maxDataPoints":1000,"maxPerRow":null,"minSpan":null,"options":{"legend":{"calcs":["last"],"displayMode":"table","placement":"bottom"},"tooltip":{"mode":"single","sort":"none"}},"repeat":null,"repeatDirection":null,"span":null,"targets":[{"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"expr":"distributed_rejected_query_counter{job=~\"$job\",instance=~\"$node\"}","format":"time_series","hide":false,"instant":false,"interval":"","intervalFactor":2,"legendFormat":"The number of rejected query in distributed execution mode","metric":"","query":"distributed_rejected_query_counter{job=~\"$job\",instance=~\"$node\"}","refId":"","step":10,"target":""}],"timeFrom":null,"timeShift":null,"title":"Rejected query in distributed execution mode","transformations":[],"transparent":false,"type":"timeseries"},{"cacheTimeout":null,"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"description":"","editable":true,"error":false,"fieldConfig":{"defaults":{"color":{"mode":"palette-classic"},"custom":{"axisLabel":"","axisPlacement":"auto","axisSoftMax":null,"axisSoftMin":null,"barAlignment":0,"drawStyle":"line","fillOpacity":10,"gradientMode":"none","hideFrom":{"legend":false,"tooltip":false,"viz":false},"lineInterpolation":"linear","lineWidth":1,"pointSize":5,"scaleDistribution":{"log":2,"type":"linear"},"showPoints":"auto","spanNulls":false,"stacking":{},"thresholdsStyle":{"mode":"off"}},"decimals":null,"mappings":[],"max":null,"min":null,"thresholds":{"mode":"absolute","steps":[]},"unit":""},"overrides":[]},"gridPos":{"h":8,"w":12,"x":0,"y":8},"height":null,"hideTimeOverride":false,"id":47,"interval":"1s","links":[],"maxDataPoints":1000,"maxPerRow":null,"minSpan":null,"options":{"legend":{"calcs":["last"],"displayMode":"table","placement":"bottom"},"tooltip":{"mode":"single","sort":"none"}},"repeat":null,"repeatDirection":null,"span":null,"targets":[{"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"expr":"distributed_completed_query_counter{job=~\"$job\",instance=~\"$node\"}","format":"time_series","hide":false,"instant":false,"interval":"","intervalFactor":2,"legendFormat":"The number of completed query in distributed execution mode","metric":"","query":"distributed_completed_query_counter{job=~\"$job\",instance=~\"$node\"}","refId":"","step":10,"target":""}],"timeFrom":null,"timeShift":null,"title":"Completed query in distributed execution mode","transformations":[],"transparent":false,"type":"timeseries"},{"cacheTimeout":null,"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"description":"","editable":true,"error":false,"fieldConfig":{"defaults":{"color":{"mode":"palette-classic"},"custom":{"axisLabel":"","axisPlacement":"auto","axisSoftMax":null,"axisSoftMin":null,"barAlignment":0,"drawStyle":"line","fillOpacity":10,"gradientMode":"none","hideFrom":{"legend":false,"tooltip":false,"viz":false},"lineInterpolation":"linear","lineWidth":1,"pointSize":5,"scaleDistribution":{"log":2,"type":"linear"},"showPoints":"auto","spanNulls":false,"stacking":{},"thresholdsStyle":{"mode":"off"}},"decimals":null,"mappings":[],"max":null,"min":null,"thresholds":{"mode":"absolute","steps":[]},"unit":"s"},"overrides":[]},"gridPos":{"h":8,"w":12,"x":12,"y":8},"height":null,"hideTimeOverride":false,"id":48,"interval":"1s","links":[],"maxDataPoints":1000,"maxPerRow":null,"minSpan":null,"options":{"legend":{"calcs":["mean"],"displayMode":"table","placement":"bottom"},"tooltip":{"mode":"single","sort":"none"}},"repeat":null,"repeatDirection":null,"span":null,"targets":[{"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"expr":"histogram_quantile(0.5, sum(rate(distributed_query_latency_bucket{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])) by (le, job, instance))","format":"time_series","hide":false,"instant":false,"interval":"","intervalFactor":2,"legendFormat":"p50 - {{job}} @ {{instance}}","metric":"","query":"histogram_quantile(0.5, sum(rate(distributed_query_latency_bucket{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])) by (le, job, instance))","refId":"","step":10,"target":""},{"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"expr":"histogram_quantile(0.9, sum(rate(distributed_query_latency_bucket{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])) by (le, job, instance))","format":"time_series","hide":false,"instant":false,"interval":"","intervalFactor":2,"legendFormat":"p90 - {{job}} @ {{instance}}","metric":"","query":"histogram_quantile(0.9, sum(rate(distributed_query_latency_bucket{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])) by (le, job, instance))","refId":"","step":10,"target":""},{"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"expr":"histogram_quantile(0.95, sum(rate(distributed_query_latency_bucket{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])) by (le, job, instance))","format":"time_series","hide":false,"instant":false,"interval":"","intervalFactor":2,"legendFormat":"p99 - {{job}} @ {{instance}}","metric":"","query":"histogram_quantile(0.95, sum(rate(distributed_query_latency_bucket{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])) by (le, job, instance))","refId":"","step":10,"target":""}],"timeFrom":null,"timeShift":null,"title":"Query Latency in Distributed Execution Mode","transformations":[],"transparent":false,"type":"timeseries"},{"cacheTimeout":null,"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"description":"","editable":true,"error":false,"fieldConfig":{"defaults":{"color":{"mode":"palette-classic"},"custom":{"axisLabel":"","axisPlacement":"auto","axisSoftMax":null,"axisSoftMin":null,"barAlignment":0,"drawStyle":"line","fillOpacity":10,"gradientMode":"none","hideFrom":{"legend":false,"tooltip":false,"viz":false},"lineInterpolation":"linear","lineWidth":1,"pointSize":5,"scaleDistribution":{"log":2,"type":"linear"},"showPoints":"auto","spanNulls":false,"stacking":{},"thresholdsStyle":{"mode":"off"}},"decimals":null,"mappings":[],"max":null,"min":null,"thresholds":{"mode":"absolute","steps":[]},"unit":"s"},"overrides":[]},"gridPos":{"h":8,"w":12,"x":0,"y":16},"height":null,"hideTimeOverride":false,"id":49,"interval":"1s","links":[],"maxDataPoints":1000,"maxPerRow":null,"minSpan":null,"options":{"legend":{"calcs":["mean"],"displayMode":"table","placement":"bottom"},"tooltip":{"mode":"single","sort":"none"}},"repeat":null,"repeatDirection":null,"span":null,"targets":[{"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"expr":"histogram_quantile(0.5, sum(rate(frontend_latency_local_execution_bucket{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])) by (le, job, instance))","format":"time_series","hide":false,"instant":false,"interval":"","intervalFactor":2,"legendFormat":"p50 - {{job}} @ {{instance}}","metric":"","query":"histogram_quantile(0.5, sum(rate(frontend_latency_local_execution_bucket{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])) by (le, job, instance))","refId":"","step":10,"target":""},{"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"expr":"histogram_quantile(0.9, sum(rate(frontend_latency_local_execution_bucket{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])) by (le, job, instance))","format":"time_series","hide":false,"instant":false,"interval":"","intervalFactor":2,"legendFormat":"p90 - {{job}} @ {{instance}}","metric":"","query":"histogram_quantile(0.9, sum(rate(frontend_latency_local_execution_bucket{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])) by (le, job, instance))","refId":"","step":10,"target":""},{"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"expr":"histogram_quantile(0.95, sum(rate(frontend_latency_local_execution_bucket{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])) by (le, job, instance))","format":"time_series","hide":false,"instant":false,"interval":"","intervalFactor":2,"legendFormat":"p99 - {{job}} @ {{instance}}","metric":"","query":"histogram_quantile(0.95, sum(rate(frontend_latency_local_execution_bucket{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])) by (le, job, instance))","refId":"","step":10,"target":""}],"timeFrom":null,"timeShift":null,"title":"Query Latency in Local Execution Mode","transformations":[],"transparent":false,"type":"timeseries"}],"repeat":null,"repeatDirection":null,"span":null,"targets":[],"timeFrom":null,"timeShift":null,"title":"Batch","transformations":[],"transparent":false,"type":"row"},{"cacheTimeout":null,"collapsed":true,"datasource":null,"description":null,"editable":true,"error":false,"fieldConfig":{"defaults":{"thresholds":{"mode":"absolute","steps":[]}}},"gridPos":{"h":1,"w":24,"x":0,"y":48},"height":null,"hideTimeOverride":false,"id":50,"interval":null,"links":[],"maxDataPoints":100,"maxPerRow":null,"minSpan":null,"panels":[{"cacheTimeout":null,"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"description":"","editable":true,"error":false,"fieldConfig":{"defaults":{"color":{"mode":"palette-classic"},"custom":{"axisLabel":"","axisPlacement":"auto","axisSoftMax":null,"axisSoftMin":null,"barAlignment":0,"drawStyle":"line","fillOpacity":10,"gradientMode":"none","hideFrom":{"legend":false,"tooltip":false,"viz":false},"lineInterpolation":"linear","lineWidth":1,"pointSize":5,"scaleDistribution":{"log":2,"type":"linear"},"showPoints":"auto","spanNulls":false,"stacking":{},"thresholdsStyle":{"mode":"off"}},"decimals":null,"mappings":[],"max":null,"min":null,"thresholds":{"mode":"absolute","steps":[]},"unit":"rows/s"},"overrides":[]},"gridPos":{"h":8,"w":12,"x":0,"y":0},"height":null,"hideTimeOverride":false,"id":51,"interval":"1s","links":[],"maxDataPoints":1000,"maxPerRow":null,"minSpan":null,"options":{"legend":{"calcs":["mean"],"displayMode":"table","placement":"bottom"},"tooltip":{"mode":"single","sort":"none"}},"repeat":null,"repeatDirection":null,"span":null,"targets":[{"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"expr":"rate(connector_source_rows_received{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])","format":"time_series","hide":false,"instant":false,"interval":"","intervalFactor":2,"legendFormat":"source={{source_type}} @ {{source_id}}","metric":"","query":"rate(connector_source_rows_received{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])","refId":"","step":10,"target":""}],"timeFrom":null,"timeShift":null,"title":"Connector Source Throughput(rows)","transformations":[],"transparent":false,"type":"timeseries"},{"cacheTimeout":null,"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"description":"","editable":true,"error":false,"fieldConfig":{"defaults":{"color":{"mode":"palette-classic"},"custom":{"axisLabel":"","axisPlacement":"auto","axisSoftMax":null,"axisSoftMin":null,"barAlignment":0,"drawStyle":"line","fillOpacity":10,"gradientMode":"none","hideFrom":{"legend":false,"tooltip":false,"viz":false},"lineInterpolation":"linear","lineWidth":1,"pointSize":5,"scaleDistribution":{"log":2,"type":"linear"},"showPoints":"auto","spanNulls":false,"stacking":{},"thresholdsStyle":{"mode":"off"}},"decimals":null,"mappings":[],"max":null,"min":null,"thresholds":{"mode":"absolute","steps":[]},"unit":"rows/s"},"overrides":[]},"gridPos":{"h":8,"w":12,"x":12,"y":0},"height":null,"hideTimeOverride":false,"id":52,"interval":"1s","links":[],"maxDataPoints":1000,"maxPerRow":null,"minSpan":null,"options":{"legend":{"calcs":["mean"],"displayMode":"table","placement":"bottom"},"tooltip":{"mode":"single","sort":"none"}},"repeat":null,"repeatDirection":null,"span":null,"targets":[{"datasource":{"type":"prometheus","uid":"risedev-prometheus"},"expr":"rate(connector_sink_rows_received{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])","format":"time_series","hide":false,"instant":false,"interval":"","intervalFactor":2,"legendFormat":"sink={{connector_type}} @ {{sink_id}}","metric":"","query":"rate(connector_sink_rows_received{job=~\"$job\",instance=~\"$node\"}[$__rate_interval])","refId":"","step":10,"target":""}],"timeFrom":null,"timeShift":null,"title":"Connector Sink Throughput(rows)","transformations":[],"transparent":false,"type":"timeseries"}],"repeat":null,"repeatDirection":null,"span":null,"targets":[],"timeFrom":null,"timeShift":null,"title":"Connector Node","transformations":[],"transparent":false,"type":"row"}],"refresh":"10s","rows":[],"schemaVersion":12,"sharedCrosshair":true,"style":"dark","tags":["risingwave"],"templating":{"list":[{"current":{"selected":false,"text":"All","value":"__all"},"definition":"label_values(process_cpu_seconds_total, instance)","description":"Reporting instance of the metric","hide":0,"includeAll":true,"label":"Node","multi":true,"name":"node","options":[],"query":{"query":"label_values(process_cpu_seconds_total, instance)","refId":"StandardVariableQuery"},"refresh":2,"regex":"","skipUrlSync":false,"sort":6,"type":"query"},{"current":{"selected":false,"text":"All","value":"__all"},"definition":"label_values(process_cpu_seconds_total, job)","description":"Reporting job of the metric","hide":0,"includeAll":true,"label":"Job","multi":true,"name":"job","options":[],"query":{"query":"label_values(process_cpu_seconds_total, job)","refId":"StandardVariableQuery"},"refresh":2,"regex":"","skipUrlSync":false,"sort":6,"type":"query"}]},"time":{"from":"now-30m","to":"now"},"timepicker":{"hidden":false,"nowDelay":null,"refresh_intervals":["5s","10s","30s","1m","5m","15m","30m","1h","2h","1d"],"time_options":["5m","15m","1h","6h","12h","24h","2d","7d","30d"]},"timezone":"browser","title":"risingwave_dashboard","uid":"Fcy3uV1nz","version":0} 2 | -------------------------------------------------------------------------------- /docker/docker-compose.yml: -------------------------------------------------------------------------------- 1 | --- 2 | version: "3" 3 | x-image: &image 4 | image: ${RW_IMAGE:-risingwavelabs/risingwave:v1.6.1} 5 | services: 6 | risingwave-standalone: 7 | <<: *image 8 | command: "standalone --meta-opts=\" \ 9 | --listen-addr 0.0.0.0:5690 \ 10 | --advertise-addr 0.0.0.0:5690 \ 11 | --dashboard-host 0.0.0.0:5691 \ 12 | --prometheus-host 0.0.0.0:1250 \ 13 | --prometheus-endpoint http://prometheus-0:9500 \ 14 | --connector-rpc-endpoint 0.0.0.0:50051 \ 15 | --backend etcd \ 16 | --etcd-endpoints etcd-0:2388 \ 17 | --state-store hummock+minio://hummockadmin:hummockadmin@minio-0:9301/hummock001 \ 18 | --data-directory hummock_001 \ 19 | --config-path /risingwave.toml\" \ 20 | --compute-opts=\" \ 21 | --config-path /risingwave.toml \ 22 | --listen-addr 0.0.0.0:5688 \ 23 | --prometheus-listener-addr 0.0.0.0:1250 \ 24 | --advertise-addr 0.0.0.0:5688 \ 25 | --async-stack-trace verbose \ 26 | --connector-rpc-endpoint 0.0.0.0:50051 \ 27 | #--parallelism 4 \ 28 | #--total-memory-bytes 8589934592 \ 29 | --role both \ 30 | --meta-address http://0.0.0.0:5690\" \ 31 | --frontend-opts=\" \ 32 | --config-path /risingwave.toml \ 33 | --listen-addr 0.0.0.0:4566 \ 34 | --advertise-addr 0.0.0.0:4566 \ 35 | --prometheus-listener-addr 0.0.0.0:1250 \ 36 | --health-check-listener-addr 0.0.0.0:6786 \ 37 | --meta-addr http://0.0.0.0:5690\" \ 38 | --compactor-opts=\" \ 39 | --listen-addr 0.0.0.0:6660 \ 40 | --prometheus-listener-addr 0.0.0.0:1250 \ 41 | --advertise-addr 0.0.0.0:6660 \ 42 | --meta-address http://0.0.0.0:5690\"" 43 | expose: 44 | - "6660" 45 | - "4566" 46 | - "5688" 47 | - "5690" 48 | - "1250" 49 | - "5691" 50 | ports: 51 | - "4566:4566" 52 | - "5690:5690" 53 | - "5691:5691" 54 | - "1250:1250" 55 | depends_on: 56 | - etcd-0 57 | - minio-0 58 | volumes: 59 | - "./risingwave.toml:/risingwave.toml" 60 | environment: 61 | RUST_BACKTRACE: "1" 62 | # If ENABLE_TELEMETRY is not set, telemetry will start by default 63 | ENABLE_TELEMETRY: ${ENABLE_TELEMETRY:-true} 64 | container_name: risingwave-standalone 65 | healthcheck: 66 | test: 67 | - CMD-SHELL 68 | - bash -c 'printf \"GET / HTTP/1.1\n\n\" > /dev/tcp/127.0.0.1/6660; exit $$?;' 69 | - bash -c 'printf \"GET / HTTP/1.1\n\n\" > /dev/tcp/127.0.0.1/5688; exit $$?;' 70 | - bash -c 'printf \"GET / HTTP/1.1\n\n\" > /dev/tcp/127.0.0.1/4566; exit $$?;' 71 | - bash -c 'printf \"GET / HTTP/1.1\n\n\" > /dev/tcp/127.0.0.1/5690; exit $$?;' 72 | interval: 1s 73 | timeout: 5s 74 | restart: always 75 | deploy: 76 | resources: 77 | limits: 78 | memory: 28G 79 | reservations: 80 | memory: 28G 81 | 82 | etcd-0: 83 | image: "quay.io/coreos/etcd:v3.5.10" 84 | command: 85 | - /usr/local/bin/etcd 86 | - "--listen-client-urls" 87 | - "http://0.0.0.0:2388" 88 | - "--advertise-client-urls" 89 | - "http://etcd-0:2388" 90 | - "--listen-peer-urls" 91 | - "http://0.0.0.0:2389" 92 | - "--initial-advertise-peer-urls" 93 | - "http://etcd-0:2389" 94 | - "--listen-metrics-urls" 95 | - "http://0.0.0.0:2379" 96 | - "--name" 97 | - risedev-meta 98 | - "--max-txn-ops" 99 | - "999999" 100 | - "--max-request-bytes" 101 | - "10485760" 102 | - "--auto-compaction-mode" 103 | - periodic 104 | - "--auto-compaction-retention" 105 | - 1m 106 | - "--snapshot-count" 107 | - "10000" 108 | - "--data-dir" 109 | - /etcd-data 110 | expose: 111 | - "2388" 112 | ports: 113 | - "2388:2388" 114 | - "2389:2389" 115 | depends_on: [] 116 | volumes: 117 | - "etcd-0:/etcd-data" 118 | environment: {} 119 | container_name: etcd-0 120 | healthcheck: 121 | test: 122 | - CMD 123 | - etcdctl 124 | - --endpoints=http://localhost:2388 125 | - endpoint 126 | - health 127 | interval: 1s 128 | timeout: 5s 129 | retries: 5 130 | restart: always 131 | 132 | grafana-0: 133 | image: "grafana/grafana-oss:latest" 134 | command: [] 135 | expose: 136 | - "3001" 137 | ports: 138 | - "3001:3001" 139 | depends_on: [] 140 | volumes: 141 | - "grafana-0:/var/lib/grafana" 142 | - "./grafana.ini:/etc/grafana/grafana.ini" 143 | - "./grafana-risedev-datasource.yml:/etc/grafana/provisioning/datasources/grafana-risedev-datasource.yml" 144 | - "./grafana-risedev-dashboard.yml:/etc/grafana/provisioning/dashboards/grafana-risedev-dashboard.yml" 145 | - "./dashboards:/dashboards" 146 | environment: {} 147 | container_name: grafana-0 148 | healthcheck: 149 | test: 150 | - CMD-SHELL 151 | - bash -c 'printf \"GET / HTTP/1.1\n\n\" > /dev/tcp/127.0.0.1/3001; exit $$?;' 152 | interval: 1s 153 | timeout: 5s 154 | retries: 5 155 | restart: always 156 | 157 | minio-0: 158 | image: "quay.io/minio/minio:latest" 159 | command: 160 | - server 161 | - "--address" 162 | - "0.0.0.0:9301" 163 | - "--console-address" 164 | - "0.0.0.0:9400" 165 | - /data 166 | expose: 167 | - "9301" 168 | - "9400" 169 | ports: 170 | - "9301:9301" 171 | - "9400:9400" 172 | depends_on: [] 173 | volumes: 174 | - "minio-0:/data" 175 | entrypoint: " 176 | 177 | /bin/sh -c ' 178 | 179 | set -e 180 | 181 | mkdir -p \"/data/hummock001\" 182 | 183 | /usr/bin/docker-entrypoint.sh \"$$0\" \"$$@\" 184 | 185 | '" 186 | environment: 187 | MINIO_CI_CD: "1" 188 | MINIO_PROMETHEUS_AUTH_TYPE: public 189 | MINIO_PROMETHEUS_URL: "http://prometheus-0:9500" 190 | MINIO_ROOT_PASSWORD: hummockadmin 191 | MINIO_ROOT_USER: hummockadmin 192 | MINIO_DOMAIN: "minio-0" 193 | container_name: minio-0 194 | healthcheck: 195 | test: 196 | - CMD-SHELL 197 | - bash -c 'printf \"GET / HTTP/1.1\n\n\" > /dev/tcp/127.0.0.1/9301; exit $$?;' 198 | interval: 1s 199 | timeout: 5s 200 | retries: 5 201 | restart: always 202 | 203 | prometheus-0: 204 | image: "prom/prometheus:latest" 205 | command: 206 | - "--config.file=/etc/prometheus/prometheus.yml" 207 | - "--storage.tsdb.path=/prometheus" 208 | - "--web.console.libraries=/usr/share/prometheus/console_libraries" 209 | - "--web.console.templates=/usr/share/prometheus/consoles" 210 | - "--web.listen-address=0.0.0.0:9500" 211 | - "--storage.tsdb.retention.time=30d" 212 | expose: 213 | - "9500" 214 | ports: 215 | - "9500:9500" 216 | depends_on: [] 217 | volumes: 218 | - "prometheus-0:/prometheus" 219 | - "./prometheus.yaml:/etc/prometheus/prometheus.yml" 220 | environment: {} 221 | container_name: prometheus-0 222 | healthcheck: 223 | test: 224 | - CMD-SHELL 225 | - sh -c 'printf "GET /-/healthy HTTP/1.0\n\n" | nc localhost 9500; exit $$?;' 226 | interval: 1s 227 | timeout: 5s 228 | retries: 5 229 | restart: always 230 | 231 | message_queue: 232 | image: "docker.vectorized.io/vectorized/redpanda:latest" 233 | command: 234 | - redpanda 235 | - start 236 | - "--smp" 237 | - "1" 238 | - "--reserve-memory" 239 | - 0M 240 | - "--memory" 241 | - 4G 242 | - "--overprovisioned" 243 | - "--node-id" 244 | - "0" 245 | - "--check=false" 246 | - "--kafka-addr" 247 | - "PLAINTEXT://0.0.0.0:29092,OUTSIDE://0.0.0.0:9092" 248 | - "--advertise-kafka-addr" 249 | - "PLAINTEXT://message_queue:29092,OUTSIDE://localhost:9092" 250 | expose: 251 | - "29092" 252 | - "9092" 253 | - "9644" 254 | ports: 255 | - "29092:29092" 256 | - "9092:9092" 257 | - "9644:9644" 258 | - "8081:8081" 259 | depends_on: [] 260 | volumes: 261 | - "message_queue:/var/lib/redpanda/data" 262 | environment: {} 263 | container_name: message_queue 264 | healthcheck: 265 | test: curl -f localhost:9644/v1/status/ready 266 | interval: 1s 267 | timeout: 5s 268 | retries: 5 269 | restart: always 270 | 271 | clickhouse: 272 | container_name: clickhouse 273 | image: clickhouse/clickhouse-server 274 | environment: 275 | - CLICKHOUSE_ADMIN_PASSWORD= 276 | ports: 277 | - '8123:8123' 278 | 279 | volumes: 280 | etcd-0: 281 | external: false 282 | grafana-0: 283 | external: false 284 | minio-0: 285 | external: false 286 | prometheus-0: 287 | external: false 288 | message_queue: 289 | external: false 290 | clickhouse: 291 | external: false -------------------------------------------------------------------------------- /docker/grafana-risedev-dashboard.yml: -------------------------------------------------------------------------------- 1 | # --- THIS FILE IS AUTO GENERATED BY RISEDEV --- 2 | apiVersion: 1 3 | 4 | providers: 5 | - name: 'risingwave-grafana' 6 | orgId: 1 7 | folder: '' 8 | folderUid: '' 9 | type: file 10 | disableDeletion: false 11 | updateIntervalSeconds: 1 12 | allowUiUpdates: true 13 | options: 14 | path: /dashboards 15 | foldersFromFilesStructure: false 16 | -------------------------------------------------------------------------------- /docker/grafana-risedev-datasource.yml: -------------------------------------------------------------------------------- 1 | # --- THIS FILE IS AUTO GENERATED BY RISEDEV --- 2 | apiVersion: 1 3 | deleteDatasources: 4 | - name: risedev-prometheus 5 | datasources: 6 | - name: risedev-prometheus 7 | type: prometheus 8 | access: proxy 9 | url: http://prometheus-0:9500 10 | withCredentials: false 11 | isDefault: true 12 | tlsAuth: false 13 | tlsAuthWithCACert: false 14 | version: 1 15 | editable: true 16 | -------------------------------------------------------------------------------- /docker/grafana.ini: -------------------------------------------------------------------------------- 1 | # --- THIS FILE IS AUTO GENERATED BY RISEDEV --- 2 | [server] 3 | http_addr = 0.0.0.0 4 | http_port = 3001 5 | 6 | [users] 7 | default_theme = light 8 | 9 | [auth.anonymous] 10 | enabled = true 11 | org_role = Admin 12 | -------------------------------------------------------------------------------- /docker/hdfs_env.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | export CLASSPATH 4 | find "$HADOOP_HOME" -iname "*.jar" -print0 | xargs -0 echo | tr ' ' ':' > temp_classpath 5 | CLASSPATH=$(cat temp_classpath):${CLASSPATH} 6 | rm temp_classpath 7 | export CLASSPATH=$HADOOP_CONF_DIR:$CLASSPATH 8 | 9 | /risingwave/bin/risingwave "$@" 10 | -------------------------------------------------------------------------------- /docker/multiple_object_storage.env: -------------------------------------------------------------------------------- 1 | RUST_BACKTRACE="1" 2 | 3 | # Google Cloud Storage 4 | # The credentials content of your service account, you can get it by executing 'cat your_credentials.json | base64 -w 0' 5 | # GOOGLE_APPLICATION_CREDENTIALS=your_credentials_json_content 6 | 7 | # Azure Blob 8 | # AZBLOB_ENDPOINT=your_endpoint 9 | # AZBLOB_ACCOUNT_NAME=your_account_name 10 | # AZBLOB_ACCOUNT_KEY=your_account_key 11 | 12 | # Ali Cloud OSS, please do not include the bucket name in the endpoint, but configure bucket name in the docker-compose-with-oss file L16 instead. 13 | # OSS_ENDPOINT=your_endpoint 14 | # OSS_ACCESS_KEY_ID=your_accrss_key_id 15 | # OSS_ACCESS_KEY_SECRET=your_accrss_key_secret 16 | 17 | # Huawei Cloud OBS, please do not include the bucket name in the endpoint, but configure bucket name in the docker-compose-with-obs file instead. 18 | # OBS_ENDPOINT=your_endpoint 19 | # OBS_ACCESS_KEY_ID=your_accrss_key_id 20 | # OBS_SECRET_ACCESS_KEY=your_secret_accrss_key -------------------------------------------------------------------------------- /docker/prometheus.yaml: -------------------------------------------------------------------------------- 1 | # --- THIS FILE IS AUTO GENERATED BY RISEDEV --- 2 | global: 3 | scrape_interval: 1s 4 | evaluation_interval: 5s 5 | 6 | scrape_configs: 7 | - job_name: prometheus 8 | static_configs: 9 | - targets: ["prometheus-0:9500"] 10 | 11 | - job_name: compute 12 | static_configs: 13 | - targets: ["compute-node-0:1222"] 14 | 15 | - job_name: meta 16 | static_configs: 17 | - targets: ["meta-node-0:1250"] 18 | 19 | - job_name: minio 20 | metrics_path: /minio/v2/metrics/cluster 21 | static_configs: 22 | - targets: ["minio-0:9301"] 23 | 24 | - job_name: compactor 25 | static_configs: 26 | - targets: ["compactor-0:1260"] 27 | 28 | - job_name: etcd 29 | static_configs: 30 | - targets: ["etcd-0:2379"] 31 | 32 | - job_name: frontend 33 | static_configs: 34 | - targets: ["frontend-node-0:2222"] 35 | 36 | - job_name: redpanda 37 | static_configs: 38 | - targets: ["message_queue:9644"] 39 | 40 | - job_name: standalone 41 | static_configs: 42 | - targets: ["risingwave-standalone:1250"] -------------------------------------------------------------------------------- /docker/risingwave.toml: -------------------------------------------------------------------------------- 1 | # RisingWave config file to be mounted into the Docker containers. 2 | # See src/config/example.toml for example 3 | -------------------------------------------------------------------------------- /homework.md: -------------------------------------------------------------------------------- 1 | # Homework 2 | 3 | ## Setting up 4 | 5 | In order to get a static set of results, we will use historical data from the dataset. 6 | 7 | Before you start on the following steps, make sure you don't have `stream-kafka` running anymore. 8 | You can switch back to the terminal running `stream-kafka` and use `Ctrl+C` to stop it. 9 | 10 | Run the following commands: 11 | ```bash 12 | # Load the cluster op commands. 13 | source commands.sh 14 | # First, reset the cluster: 15 | clean-cluster 16 | # Start a new cluster 17 | start-cluster 18 | # wait for cluster to start 19 | sleep 5 20 | # Seed historical data instead of real-time data 21 | seed-kafka 22 | # Recreate trip data table 23 | psql -f risingwave-sql/table/trip_data.sql 24 | # Wait for a while for the trip_data table to be populated. 25 | sleep 5 26 | # Check that you have 100K records in the trip_data table 27 | # You may rerun it if the count is not 100K 28 | psql -c "SELECT COUNT(*) FROM trip_data" 29 | ``` 30 | 31 | ## Question 0 32 | 33 | _This question is just a warm-up to introduce dynamic filter, please attempt it before viewing its solution._ 34 | 35 | What are the dropoff taxi zones at the latest dropoff times? 36 | 37 | For this part, we will use the [dynamic filter pattern](https://docs.risingwave.com/docs/current/sql-pattern-dynamic-filters/). 38 | 39 |
40 | Solution 41 | 42 | ```sql 43 | CREATE MATERIALIZED VIEW latest_dropoff_time AS 44 | WITH t AS ( 45 | SELECT MAX(tpep_dropoff_datetime) AS latest_dropoff_time 46 | FROM trip_data 47 | ) 48 | SELECT taxi_zone.Zone as taxi_zone, latest_dropoff_time 49 | FROM t, 50 | trip_data 51 | JOIN taxi_zone 52 | ON trip_data.DOLocationID = taxi_zone.location_id 53 | WHERE trip_data.tpep_dropoff_datetime = t.latest_dropoff_time; 54 | 55 | -- taxi_zone | latest_dropoff_time 56 | -- ----------------+--------------------- 57 | -- Midtown Center | 2022-01-03 17:24:54 58 | -- (1 row) 59 | ``` 60 | 61 |
62 | 63 | ## Question 1 64 | 65 | Create a materialized view to compute the average, min and max trip time **between each taxi zone**. 66 | 67 | Note that we consider the do not consider `a->b` and `b->a` as the same trip pair. 68 | So as an example, you would consider the following trip pairs as different pairs: 69 | ```plaintext 70 | Yorkville East -> Steinway 71 | Steinway -> Yorkville East 72 | ``` 73 | 74 | From this MV, find the pair of taxi zones with the highest average trip time. 75 | You may need to use the [dynamic filter pattern](https://docs.risingwave.com/docs/current/sql-pattern-dynamic-filters/) for this. 76 | 77 | Bonus (no marks): Create an MV which can identify anomalies in the data. For example, if the average trip time between two zones is 1 minute, 78 | but the max trip time is 10 minutes and 20 minutes respectively. 79 | 80 | Options: 81 | 1. Yorkville East, Steinway 82 | 2. Murray Hill, Midwood 83 | 3. East Flatbush/Farragut, East Harlem North 84 | 4. Midtown Center, University Heights/Morris Heights 85 | 86 | p.s. The trip time between taxi zones does not take symmetricity into account, i.e. `A -> B` and `B -> A` are considered different trips. This applies to subsequent questions as well. 87 | 88 | ## Question 2 89 | 90 | Recreate the MV(s) in question 1, to also find the **number of trips** for the pair of taxi zones with the highest average trip time. 91 | 92 | Options: 93 | 1. 5 94 | 2. 3 95 | 3. 10 96 | 4. 1 97 | 98 | ## Question 3 99 | 100 | From the latest pickup time to 17 hours before, what are the top 3 busiest zones in terms of number of pickups? 101 | For example if the latest pickup time is 2020-01-01 17:00:00, 102 | then the query should return the top 3 busiest zones from 2020-01-01 00:00:00 to 2020-01-01 17:00:00. 103 | 104 | HINT: You can use [dynamic filter pattern](https://docs.risingwave.com/docs/current/sql-pattern-dynamic-filters/) 105 | to create a filter condition based on the latest pickup time. 106 | 107 | NOTE: For this question `17 hours` was picked to ensure we have enough data to work with. 108 | 109 | Options: 110 | 1. Clinton East, Upper East Side North, Penn Station 111 | 2. LaGuardia Airport, Lincoln Square East, JFK Airport 112 | 3. Midtown Center, Upper East Side South, Upper East Side North 113 | 4. LaGuardia Airport, Midtown Center, Upper East Side North -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 |
5 | 6 | 7 | 8 | 9 | 10 | 120 | 121 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | blinker==1.7.0 2 | click==8.1.7 3 | confluent-kafka==2.3.0 4 | Flask==3.0.2 5 | Flask-Cors==4.0.0 6 | itsdangerous==2.1.2 7 | Jinja2==3.1.3 8 | MarkupSafe==2.1.5 9 | numpy==1.26.4 10 | pandas==2.2.0 11 | psycopg2==2.9.9 12 | pyarrow==15.0.0 13 | python-dateutil==2.8.2 14 | pytz==2024.1 15 | six==1.16.0 16 | tzdata==2024.1 17 | Werkzeug==3.0.1 18 | -------------------------------------------------------------------------------- /risingwave-sql/sink/avg_fare_amt_sink.sql: -------------------------------------------------------------------------------- 1 | CREATE SINK IF NOT EXISTS avg_fare_amt_sink AS SELECT avg_fare_amount_per_hour, num_rides_per_hour FROM avg_fare_amt 2 | WITH ( 3 | connector = 'clickhouse', 4 | type = 'append-only', 5 | clickhouse.url = 'http://clickhouse:8123', 6 | clickhouse.user = '', 7 | clickhouse.password = '', 8 | clickhouse.database = 'default', 9 | clickhouse.table='avg_fare_amt', 10 | force_append_only = 'true' 11 | ); -------------------------------------------------------------------------------- /risingwave-sql/sink/demo_clickhouse_sink.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE IF NOT EXISTS demo_test( 2 | seq_id int, 3 | user_id int, 4 | user_name String 5 | ) append only; 6 | 7 | CREATE SINK IF NOT EXISTS demo_test_sink FROM demo_test 8 | WITH ( 9 | connector = 'clickhouse', 10 | type = 'append-only', 11 | clickhouse.url = 'http://clickhouse:8123', 12 | clickhouse.user = '', 13 | clickhouse.password = '', 14 | clickhouse.database = 'default', 15 | clickhouse.table='demo_test', 16 | ); -------------------------------------------------------------------------------- /risingwave-sql/table/taxi_zone.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE taxi_zone ( 2 | location_id int, 3 | borough text, 4 | zone text, 5 | service_zone text 6 | ); -------------------------------------------------------------------------------- /risingwave-sql/table/trip_data.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE if not exists trip_data ( 2 | -- See: https://www.nyc.gov/assets/tlc/downloads/pdf/data_dictionary_trip_records_yellow.pdf 3 | -- Taxicab Technology Service Provider or TPEP 4 | -- 1= Creative Mobile Technologies, LLC; 2= VeriFone Inc 5 | VendorID bigint, 6 | -- The date and time when the meter was engaged. 7 | tpep_pickup_datetime timestamp, 8 | -- The date and time when the meter was disengaged. 9 | tpep_dropoff_datetime timestamp, 10 | -- The number of passengers in the vehicle. This is a driver-entered value. 11 | passenger_count numeric, 12 | -- The elapsed trip distance in miles reported by the taximeter. 13 | trip_distance numeric, 14 | -- The final rate code in effect at the end of the trip. 15 | -- 16 | -- 1= Standard rate 17 | -- 2= JFK 18 | -- 3= Newark 19 | -- 4= Nassau or Westchester 20 | -- 5= Negotiated fare 21 | -- 6= Group ride 22 | RatecodeID numeric, 23 | -- This flag indicates whether the trip record was held in vehicle memory before sending to the vendor, 24 | -- aka “store and forward,” because the vehicle did not have a connection to the server. 25 | store_and_fwd_flag string, 26 | -- TLC Taxi Zone in which the taximeter was engaged 27 | PULocationID bigint, 28 | -- TLC Taxi Zone in which the taximeter was disengaged 29 | DOLocationID bigint, 30 | -- A numeric code signifying how the passenger paid for the trip. 31 | -- 32 | -- 1= Credit card 33 | -- 2= Cash 34 | -- 3= No charge 35 | -- 4= Dispute 36 | -- 5= Unknown 37 | -- 6= Voided trip 38 | payment_type bigint, 39 | -- The time-and-distance fare calculated by the meter. 40 | fare_amount numeric, 41 | -- Miscellaneous extras and surcharges. Currently, this only includes the 0.50 and 1 rush hour and overnight charges. 42 | extra numeric, 43 | -- 0.50 MTA tax that is automatically triggered based on the metered rate in use. 44 | mta_tax numeric, 45 | -- This field is automatically populated for credit card tips. Cash tips are not included. 46 | tip_amount numeric, 47 | -- The amount of the tolls paid in cash. 48 | tolls_amount numeric, 49 | -- 0.30 improvement surcharge assessed on hailed trips at the flag drop. 50 | improvement_surcharge numeric, 51 | -- The total amount charged to passengers. Does not include cash tips. 52 | total_amount numeric, 53 | -- The 2.75 congestion surcharge is a New York State MTA tax. 54 | congestion_surcharge numeric, 55 | -- $1.25 for pick up only at LaGuardia Airport and John F. Kennedy International Airport. 56 | airport_fee numeric 57 | ) WITH ( 58 | connector='kafka', 59 | topic='trip_data', 60 | properties.bootstrap.server='message_queue:29092' 61 | ) FORMAT PLAIN ENCODE JSON; -------------------------------------------------------------------------------- /seed_kafka.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import datetime 4 | import random 5 | import sys 6 | 7 | import psycopg2 8 | import pyarrow.parquet as pq 9 | from confluent_kafka import Producer 10 | from confluent_kafka.admin import AdminClient, NewTopic 11 | import pandas 12 | import time 13 | import logging 14 | 15 | logging.basicConfig() 16 | logging.root.setLevel(logging.INFO) 17 | 18 | 19 | class Env: 20 | def __init__(self, conf): 21 | self.conf = conf 22 | self.producer = Producer(conf) 23 | self.admin_client = AdminClient(conf) 24 | 25 | 26 | def check_kafka_topic_created(env, topic): 27 | admin_client = env.admin_client 28 | cluster_metadata = admin_client.list_topics() 29 | return topic in cluster_metadata.topics.keys() 30 | 31 | 32 | def create_kafka_topic(env, topic_name): 33 | admin_client = env.admin_client 34 | topic = NewTopic(topic=topic_name, num_partitions=8, replication_factor=1) 35 | 36 | if check_kafka_topic_created(env, topic_name): 37 | logging.warning(f'Topic {topic_name} already exists, deleting it') 38 | admin_client.delete_topics([topic_name])[topic_name].result() 39 | admin_client.create_topics([topic])[topic_name].result() 40 | 41 | if check_kafka_topic_created(env, topic_name): 42 | logging.info(f'Topic {topic_name} created') 43 | else: 44 | logging.error(f'Topic {topic_name} not created') 45 | raise Exception(f'Topic {topic_name} not created') 46 | 47 | 48 | def send_records_to_kafka(env, records, real_time=False): 49 | producer = env.producer 50 | records_count = len(records) 51 | if not real_time: 52 | logging.info(f"Sending 100,000 records to Kafka") 53 | else: 54 | logging.info(f"Sending {records_count} records to Kafka") 55 | for i, (_, record) in enumerate(records.iterrows()): 56 | # Limit historical data to 100000 records, since cluster resource may be limited. 57 | if not real_time and i >= 100000: 58 | break 59 | 60 | if i == 0: 61 | logging.debug("tpep_pickup_datetime", record['tpep_pickup_datetime']) 62 | logging.debug("tpep_dropoff_datetime", record['tpep_dropoff_datetime']) 63 | 64 | if real_time: 65 | 66 | tpep_interval = record['tpep_dropoff_datetime'] - record['tpep_pickup_datetime'] 67 | tpep_dropoff_datetime = datetime.datetime.now(datetime.timezone.utc) 68 | tpep_pickup_datetime = tpep_dropoff_datetime - tpep_interval 69 | record['tpep_pickup_datetime'] = tpep_pickup_datetime 70 | record['tpep_dropoff_datetime'] = tpep_dropoff_datetime 71 | time.sleep(random.randrange(0, 100) / 1000) 72 | if i % 100 == 0: 73 | logging.info(f"Sent {i} records") 74 | 75 | message = record.to_json() 76 | 77 | producer.produce('trip_data', value=message.encode(), key=None) 78 | if i % env.conf["queue.buffering.max.messages"] == 0: 79 | producer.flush() 80 | 81 | if i % 100000 == 0: 82 | logging.info(f"Sent {i} records") 83 | 84 | producer.flush() 85 | if not real_time: 86 | logging.info(f"Sent 100,000 records to Kafka") 87 | else: 88 | logging.info(f"Sent {records_count} records to Kafka") 89 | 90 | 91 | def send_parquet_records(env, parquet_file, real_time=False): 92 | table = pq.read_table(parquet_file) 93 | records = table.to_pandas() 94 | send_records_to_kafka(env, records, real_time) 95 | 96 | 97 | def check_connection(conn): 98 | cur = conn.cursor() 99 | logging.info('Checking connection to the RisingWave') 100 | cur.execute("SELECT version();") 101 | result = cur.fetchone() 102 | if result is None: 103 | logging.error('Connection failed') 104 | raise Exception('Connection failed') 105 | conn.commit() 106 | logging.info(f'RisingWave started with version: {result[0]}') 107 | 108 | 109 | def send_csv_records(env, csv_file): 110 | records = pandas.read_csv(csv_file) 111 | # connect to risingwave via psycopg2 112 | conn = psycopg2.connect( 113 | host="localhost", 114 | database="dev", 115 | user="root", 116 | port=4566, 117 | ) 118 | conn.set_session(autocommit=True) 119 | check_connection(conn) 120 | # For each record in the csv file, insert it into the database 121 | cur = conn.cursor() 122 | # Recreate table if it exists 123 | cur.execute("DROP TABLE IF EXISTS taxi_zone CASCADE;") 124 | cur.execute( 125 | """ 126 | CREATE TABLE taxi_zone ( 127 | location_id int, 128 | borough text, 129 | zone text, 130 | service_zone text 131 | ) 132 | """ 133 | ) 134 | logging.info('Created taxi_zone table') 135 | for i, record in records.iterrows(): 136 | location_id = record['LocationID'] 137 | borough = record['Borough'] 138 | zone = record['Zone'] 139 | service_zone = record['service_zone'] 140 | cur.execute( 141 | """ 142 | INSERT INTO taxi_zone (location_id, borough, zone, service_zone) 143 | VALUES (%s, %s, %s, %s); 144 | """, 145 | (location_id, borough, zone, service_zone)) 146 | cur.execute("flush;") 147 | conn.commit() 148 | conn.close() 149 | logging.info(f'Created {len(records)} records in taxi_zone table') 150 | 151 | 152 | def main(): 153 | update = len(sys.argv) >= 2 and sys.argv[1] == "update" 154 | conf = { 155 | 'bootstrap.servers': "localhost:9092", 156 | "queue.buffering.max.messages": 1000000 157 | } 158 | env = Env(conf) 159 | 160 | # Load taxi zone data 161 | logging.info('Loading taxi zone data') 162 | taxi_zone_filepath = 'data/taxi_zone.csv' 163 | send_csv_records(env, taxi_zone_filepath) 164 | 165 | # Load trip data 166 | logging.info('Loading trip data') 167 | trip_data_topic = 'trip_data' 168 | trip_data_filepath = 'data/yellow_tripdata_2022-01.parquet' 169 | create_kafka_topic(env, trip_data_topic) 170 | 171 | if update: 172 | logging.info('Starting real time updates') 173 | else: 174 | logging.info('Sending historical data') 175 | send_parquet_records(env, trip_data_filepath, real_time=update) 176 | 177 | 178 | main() 179 | -------------------------------------------------------------------------------- /server.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | from flask import Flask, jsonify 4 | import psycopg2 5 | from flask_cors import CORS 6 | 7 | app = Flask(__name__) 8 | CORS(app) 9 | 10 | # Replace the following with your PostgreSQL database connection details 11 | db_connection_params = { 12 | 'host': 'localhost', 13 | 'database': 'dev', 14 | 'user': 'root', 15 | 'port': 4566, 16 | } 17 | 18 | def run_query(query): 19 | connection = psycopg2.connect(**db_connection_params) 20 | cursor = connection.cursor() 21 | cursor.execute(query) 22 | result = cursor.fetchall() 23 | connection.close() 24 | return result 25 | 26 | @app.route('/get_busiest_zones', methods=['GET']) 27 | def get_busiest_zones(): 28 | # Replace the following with your SQL query for busiest zones 29 | query = 'SELECT * FROM busiest_zones_1_min' 30 | result = run_query(query) 31 | return jsonify(result) 32 | 33 | @app.route('/get_longest_trips', methods=['GET']) 34 | def get_longest_trips(): 35 | # Replace the following with your SQL query for longest trips 36 | query = 'SELECT * FROM longest_trip_1_min' 37 | result = run_query(query) 38 | return jsonify(result) 39 | 40 | if __name__ == '__main__': 41 | app.run(debug=True) -------------------------------------------------------------------------------- /slides.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/risingwavelabs/risingwave-data-talks-workshop-2024-03-04/c35d3d9de58f174853b5f29439241c966d88964f/slides.pdf -------------------------------------------------------------------------------- /workshop.md: -------------------------------------------------------------------------------- 1 | # Stream Processing in SQL with RisingWave 2 | 3 | ![project](./assets/project.png) 4 | 5 | Before beginning on this section, make sure you have setup your environment according to the [README](./README.md). 6 | 7 | Note that in every new terminal you should run the following command to load the environment variables and commands: 8 | ```bash 9 | source commands.sh 10 | ``` 11 | 12 | ## Setting up RisingWave with Docker Compose 13 | 14 | Reference: https://docs.risingwave.com/docs/current/risingwave-docker-compose/ 15 | 16 | For this workshop, I have slightly modified the `docker-compose.yml` file to include clickhouse as well. 17 | 18 | The `docker-compose.yml` file is located in the `docker` directory. 19 | 20 | It contains the following key components: 21 | - RisingWave (Stream Processing) 22 | - Clickhouse (Downstream Delivery) 23 | - Redpanda (Upstream Ingestion) 24 | - Grafana (Visualization) 25 | - Prometheus (Metrics) 26 | - MinIO (Storage) 27 | - Etcd (Metadata Storage) 28 | 29 | ## Ingesting Data into RisingWave using Kafka 30 | 31 | Reference: 32 | - https://docs.risingwave.com/docs/current/ingest-from-kafka/ 33 | - https://docs.risingwave.com/docs/current/data-ingestion/ 34 | 35 | The `seed_kafka.py` file contains the logic to process the data and populate RisingWave. 36 | 37 | Here we: 38 | 1. Process the `taxi_zone` data and insert it into RisingWave. This is just ingested with DML over `psycog`, since it's a small dataset. 39 | 2. Process the `trip_data` and insert it into RisingWave. This is ingested via Kafka. 40 | 41 | In order to simulate real-time data, we will replace the `timestamp` fields in the `trip_data` with `timestamp`s close to the current time. 42 | 43 | Let's start ingestion into RisingWave by running it: 44 | ```bash 45 | stream-kafka 46 | ``` 47 | 48 | Now we can let that run in the background. 49 | 50 | Let's open another terminal to create the trip_data table: 51 | ```bash 52 | source commands.sh 53 | psql -f risingwave-sql/table/trip_data.sql 54 | ``` 55 | 56 | You may look at their definitions by running: 57 | ```bash 58 | psql -c 'SHOW TABLES;' 59 | ``` 60 | 61 | ## Stream Processing with Materialized Views in RisingWave 62 | 63 | ### Validating the ingested data 64 | 65 | Now we are ready to begin processing the real-time stream being ingested into RisingWave! 66 | 67 | The first thing we will do is to check `taxi_zone` and `trip_data`, to make sure 68 | the data has been ingested correctly. 69 | 70 | Let's start a `psql` session. 71 | ```bash 72 | source commands.sh 73 | psql 74 | ``` 75 | 76 | First, we verify `taxi_zone`, since this is static data: 77 | ```sql 78 | SELECT * FROM taxi_zone; 79 | ``` 80 | 81 | We will also query for recent data, to ensure we are getting real-time data. 82 | 83 | ```sql 84 | SELECT pulocationid, dolocationid, tpep_pickup_datetime, tpep_dropoff_datetime 85 | FROM trip_data WHERE tpep_dropoff_datetime > now() - interval '1 minute'; 86 | ``` 87 | 88 | We can join this with `taxi_zone` to get the names of the zones. 89 | 90 | ```sql 91 | SELECT taxi_zone.Zone as pickup_zone, taxi_zone_1.Zone as dropoff_zone, tpep_pickup_datetime, tpep_dropoff_datetime 92 | FROM trip_data 93 | JOIN taxi_zone ON trip_data.PULocationID = taxi_zone.location_id 94 | JOIN taxi_zone as taxi_zone_1 ON trip_data.DOLocationID = taxi_zone_1.location_id 95 | WHERE tpep_dropoff_datetime > now() - interval '1 minute'; 96 | ``` 97 | 98 | And finally make it into an MV so we can constantly query the latest realtime data: 99 | ```sql 100 | CREATE MATERIALIZED VIEW latest_1min_trip_data AS 101 | SELECT taxi_zone.Zone as pickup_zone, taxi_zone_1.Zone as dropoff_zone, tpep_pickup_datetime, tpep_dropoff_datetime 102 | FROM trip_data 103 | JOIN taxi_zone ON trip_data.PULocationID = taxi_zone.location_id 104 | JOIN taxi_zone as taxi_zone_1 ON trip_data.DOLocationID = taxi_zone_1.location_id 105 | WHERE tpep_dropoff_datetime > now() - interval '1 minute'; 106 | ``` 107 | 108 | We can now query the MV to see the latest data: 109 | ```sql 110 | SELECT * FROM latest_1min_trip_data order by tpep_dropoff_datetime DESC; 111 | ``` 112 | 113 | Now we can start processing the data with Materialized Views, to provide analysis of the data stream! 114 | 115 | ### Materialized View 1: Total Airport Pickups 116 | 117 | The first materialized view we create will be to count the total number of pickups at the airports. 118 | 119 | This is rather simple, we just need to filter the `PULocationID` to the airport IDs. 120 | 121 | Recall `taxi_zone` contains metadata around the taxi zones, so we can use that to figure out the airport zones. 122 | ```sql 123 | describe taxi_zone; 124 | ``` 125 | 126 | Let's first get the zone names by looking at the `taxi_zone` table: 127 | ```sql 128 | SELECT * FROM taxi_zone WHERE Zone LIKE '%Airport'; 129 | ``` 130 | 131 | Then we can simply join on their location ids to get all the trips: 132 | ```sql 133 | SELECT 134 | * 135 | FROM 136 | trip_data 137 | JOIN taxi_zone 138 | ON trip_data.PULocationID = taxi_zone.location_id 139 | WHERE taxi_zone.Zone LIKE '%Airport'; 140 | ``` 141 | 142 | And finally apply the `count(*)` aggregation for each airport. 143 | 144 | ```sql 145 | SELECT 146 | count(*) AS cnt, 147 | taxi_zone.Zone 148 | FROM 149 | trip_data 150 | JOIN taxi_zone 151 | ON trip_data.PULocationID = taxi_zone.location_id 152 | WHERE taxi_zone.Zone LIKE '%Airport' 153 | GROUP BY taxi_zone.Zone; 154 | ``` 155 | 156 | We can now create a Materialized View to constantly query the latest data: 157 | ```sql 158 | CREATE MATERIALIZED VIEW total_airport_pickups AS 159 | SELECT 160 | count(*) AS cnt, 161 | taxi_zone.Zone 162 | FROM 163 | trip_data 164 | JOIN taxi_zone 165 | ON trip_data.PULocationID = taxi_zone.location_id 166 | WHERE taxi_zone.Zone LIKE '%Airport' 167 | GROUP BY taxi_zone.Zone; 168 | ``` 169 | 170 | We can now query the MV to see the latest data: 171 | ```sql 172 | SELECT * FROM total_airport_pickups; 173 | ``` 174 | 175 | So what actually happens for the MV? 176 | 177 | We can examine the query plan to see what's happening: 178 | ```sql 179 | EXPLAIN CREATE MATERIALIZED VIEW total_airport_pickups AS 180 | SELECT 181 | count(*) AS cnt, 182 | taxi_zone.Zone 183 | FROM 184 | trip_data 185 | JOIN taxi_zone 186 | ON trip_data.PULocationID = taxi_zone.location_id 187 | WHERE taxi_zone.Zone LIKE '%Airport' 188 | GROUP BY taxi_zone.Zone; 189 | ``` 190 | 191 | ``` 192 | QUERY PLAN 193 | ------------------------------------------------------------------------------------------------------------------ 194 | StreamMaterialize { columns: [cnt, zone], stream_key: [zone], pk_columns: [zone], pk_conflict: NoCheck } 195 | └─StreamProject { exprs: [count, taxi_zone.zone] } 196 | └─StreamHashAgg { group_key: [taxi_zone.zone], aggs: [count] } 197 | ^-- apply the count aggregation 198 | └─StreamExchange { dist: HashShard(taxi_zone.zone) } 199 | └─StreamHashJoin { type: Inner, predicate: trip_data.pulocationid = $expr1 } 200 | ^-- join them with a predicate 201 | ├─StreamExchange { dist: HashShard(trip_data.pulocationid) } 202 | │ └─StreamTableScan { table: trip_data, columns: [pulocationid, _row_id] } 203 | ^-- scan from trip_data 204 | └─StreamExchange { dist: HashShard($expr1) } 205 | └─StreamProject { exprs: [taxi_zone.zone, taxi_zone.location_id::Int64 as $expr1, taxi_zone._row_id] } 206 | └─StreamFilter { predicate: Like(taxi_zone.zone, '%Airport':Varchar) } 207 | └─StreamTableScan { table: taxi_zone, columns: [location_id, zone, _row_id] } 208 | ^-- Scan from taxi_zone 209 | ``` 210 | 211 | Go to your local [RisingWave Dashboard](http://localhost:5691) to see the query plan. 212 | 213 | Provided a simplified a simpler version here: 214 | 215 | ![query_plan](./assets/mv1_plan.png) 216 | 217 | ```sql 218 | CREATE MATERIALIZED VIEW total_airport_pickups AS 219 | SELECT 220 | count(*) AS cnt, 221 | taxi_zone.Zone 222 | FROM 223 | trip_data 224 | JOIN taxi_zone 225 | ON trip_data.PULocationID = taxi_zone.location_id 226 | WHERE taxi_zone.Zone LIKE '%Airport' 227 | GROUP BY taxi_zone.Zone; 228 | ``` 229 | 230 | ### Materialized View 2: Airport pickups from JFK Airport, 1 hour before the latest pickup 231 | 232 | We can adapt the previous MV to create a more specific one. 233 | We no longer need the `GROUP BY`, since we are only interested in 1 taxi zone, JFK Airport. 234 | 235 | ```sql 236 | CREATE MATERIALIZED VIEW airport_pu as 237 | SELECT 238 | tpep_pickup_datetime, 239 | pulocationid 240 | FROM 241 | trip_data 242 | JOIN taxi_zone 243 | ON trip_data.PULocationID = taxi_zone.location_id 244 | WHERE 245 | taxi_zone.Borough = 'Queens' 246 | AND taxi_zone.Zone = 'JFK Airport'; 247 | ``` 248 | 249 | Next, we also want to keep track of the latest pickup 250 | ```sql 251 | CREATE MATERIALIZED VIEW latest_jfk_pickup AS 252 | SELECT 253 | max(tpep_pickup_datetime) AS latest_pickup_time 254 | FROM 255 | trip_data 256 | JOIN taxi_zone 257 | ON trip_data.PULocationID = taxi_zone.location_id 258 | WHERE 259 | taxi_zone.Borough = 'Queens' 260 | AND taxi_zone.Zone = 'JFK Airport'; 261 | ``` 262 | 263 | Finally, let's get the counts of the pickups from JFK Airport, 1 hour before the latest pickup 264 | ```sql 265 | CREATE MATERIALIZED VIEW jfk_pickups_1hr_before AS 266 | SELECT 267 | count(*) AS cnt 268 | FROM 269 | airport_pu 270 | JOIN latest_jfk_pickup 271 | ON airport_pu.tpep_pickup_datetime > latest_jfk_pickup.latest_pickup_time - interval '1 hour' 272 | JOIN taxi_zone 273 | ON airport_pu.PULocationID = taxi_zone.location_id 274 | WHERE 275 | taxi_zone.Borough = 'Queens' 276 | AND taxi_zone.Zone = 'JFK Airport'; 277 | ``` 278 | 279 | Simplified query plan: 280 | 281 | ![query_plan](./assets/mv2_plan.png) 282 | 283 | ### Materialized View 3: Top 10 busiest zones in the last 1 minute 284 | 285 | First we can write a query to get the counts of the pickups from each zone. 286 | 287 | ```sql 288 | SELECT 289 | taxi_zone.Zone AS dropoff_zone, 290 | count(*) AS last_1_min_dropoff_cnt 291 | FROM 292 | trip_data 293 | JOIN taxi_zone 294 | ON trip_data.DOLocationID = taxi_zone.location_id 295 | GROUP BY 296 | taxi_zone.Zone 297 | ORDER BY last_1_min_dropoff_cnt DESC 298 | LIMIT 10; 299 | ``` 300 | 301 | Next, we can create a temporal filter to get the counts of the pickups from each zone in the last 1 minute. 302 | 303 | That has the form: 304 | ```sql 305 | WHERE 306 | 'timestamp-column' > (NOW() - INTERVAL '1' MINUTE) 307 | ``` 308 | 309 | ```sql 310 | CREATE MATERIALIZED VIEW busiest_zones_1_min AS SELECT 311 | taxi_zone.Zone AS dropoff_zone, 312 | count(*) AS last_1_min_dropoff_cnt 313 | FROM 314 | trip_data 315 | JOIN taxi_zone 316 | ON trip_data.DOLocationID = taxi_zone.location_id 317 | WHERE 318 | trip_data.tpep_dropoff_datetime > (NOW() - INTERVAL '1' MINUTE) 319 | GROUP BY 320 | taxi_zone.Zone 321 | ORDER BY last_1_min_dropoff_cnt DESC 322 | LIMIT 10; 323 | ``` 324 | 325 | Didn't include the query plan this time, you may look at the dashboard. 326 | 327 | ### Materialized View 4: Longest trips 328 | 329 | Here, the concept is similar as the previous MV, but we are interested in the top 10 longest trips for the last 5 min. 330 | 331 | First we create the query to get the longest trips: 332 | ```sql 333 | SELECT 334 | tpep_pickup_datetime, 335 | tpep_dropoff_datetime, 336 | taxi_zone_pu.Zone as pickup_zone, 337 | taxi_zone_do.Zone as dropoff_zone, 338 | trip_distance 339 | FROM 340 | trip_data 341 | JOIN taxi_zone as taxi_zone_pu 342 | ON trip_data.PULocationID = taxi_zone_pu.location_id 343 | JOIN taxi_zone as taxi_zone_do 344 | ON trip_data.DOLocationID = taxi_zone_do.location_id 345 | ORDER BY 346 | trip_distance DESC 347 | LIMIT 10; 348 | ``` 349 | 350 | Then we can create a temporal filter to get the longest trips for the last 5 minutes: 351 | ```sql 352 | CREATE MATERIALIZED VIEW longest_trip_1_min AS SELECT 353 | tpep_pickup_datetime, 354 | tpep_dropoff_datetime, 355 | taxi_zone_pu.Zone as pickup_zone, 356 | taxi_zone_do.Zone as dropoff_zone, 357 | trip_distance 358 | FROM 359 | trip_data 360 | JOIN taxi_zone as taxi_zone_pu 361 | ON trip_data.PULocationID = taxi_zone_pu.location_id 362 | JOIN taxi_zone as taxi_zone_do 363 | ON trip_data.DOLocationID = taxi_zone_do.location_id 364 | WHERE 365 | trip_data.tpep_pickup_datetime > (NOW() - INTERVAL '5' MINUTE) 366 | ORDER BY 367 | trip_distance DESC 368 | LIMIT 10; 369 | ``` 370 | 371 | Didn't include the query plan this time, you may look at the dashboard. 372 | 373 | After this, you may run the visualization dashboard to see the data in real-time. 374 | 375 | Start the backend which queries RisingWave: 376 | ```bash 377 | ./server.py 378 | ``` 379 | 380 | ### Visualize Data from Materialized View 3 and 4 381 | 382 | Start the frontend, in a separate terminal, if you're on OSX: 383 | ```bash 384 | open index.html 385 | ``` 386 | 387 | Start the frontend, in a separate terminal, if you're on linux: 388 | ```bash 389 | xdg-open index.html 390 | ``` 391 | 392 | ### Materialized View 5: Average Fare Amount vs Number of rides 393 | 394 | How does `avg_fare_amt` change relative to number of pickups per minute? 395 | 396 | We use something known as a [tumble window function](https://docs.risingwave.com/docs/current/sql-function-time-window/#tumble-time-window-function), to compute this. 397 | 398 | ```sql 399 | CREATE MATERIALIZED VIEW avg_fare_amt AS 400 | SELECT 401 | avg(fare_amount) AS avg_fare_amount_per_min, 402 | count(*) AS num_rides_per_min, 403 | window_start, 404 | window_end 405 | FROM 406 | TUMBLE(trip_data, tpep_pickup_datetime, INTERVAL '1' MINUTE) 407 | GROUP BY 408 | window_start, window_end 409 | ORDER BY 410 | num_rides_per_min ASC; 411 | ``` 412 | 413 | For each window we compute the average fare amount and the number of rides. 414 | 415 | That's all for the materialized views! 416 | 417 | Now we will see how to sink the data out from RisingWave. 418 | 419 | ## How to sink data from RisingWave to Clickhouse 420 | 421 | Reference: 422 | - https://docs.risingwave.com/docs/current/data-delivery/ 423 | - https://docs.risingwave.com/docs/current/sink-to-clickhouse/ 424 | 425 | We have done some simple analytics and processing of the data in RisingWave. 426 | 427 | Now we want to sink the data out to Clickhouse, for further analysis. 428 | 429 | We will create a Clickhouse table to store the data from the materialized views. 430 | 431 | ```sql 432 | CREATE TABLE avg_fare_amt( 433 | avg_fare_amount_per_min numeric, 434 | num_rides_per_min Int64, 435 | ) ENGINE = ReplacingMergeTree 436 | PRIMARY KEY (avg_fare_amount_per_min, num_rides_per_min); 437 | ``` 438 | 439 | We will create a Clickhouse sink to sink the data from the materialized views to the Clickhouse table. 440 | 441 | ```sql 442 | CREATE SINK IF NOT EXISTS avg_fare_amt_sink AS SELECT avg_fare_amount_per_min, num_rides_per_min FROM avg_fare_amt 443 | WITH ( 444 | connector = 'clickhouse', 445 | type = 'append-only', 446 | clickhouse.url = 'http://clickhouse:8123', 447 | clickhouse.user = '', 448 | clickhouse.password = '', 449 | clickhouse.database = 'default', 450 | clickhouse.table='avg_fare_amt', 451 | force_append_only = 'true' 452 | ); 453 | ``` 454 | 455 | Now we can run queries on the data ingested into clickhouse: 456 | ```bash 457 | clickhouse-client-term 458 | ``` 459 | 460 | Run some queries in `Clickhouse` 461 | ```sql 462 | select max(avg_fare_amount_per_min) from avg_fare_amt; 463 | select min(avg_fare_amount_per_min) from avg_fare_amt; 464 | ``` 465 | 466 | ## Summary 467 | 468 | In this workshop you have learnt: 469 | - How to ingest data into RisingWave using Kafka 470 | - How to process the data using Materialized Views 471 | - Using Aggregations 472 | - Using Temporal Filters 473 | - Using Window Functions (Tumble) 474 | - Using Joins 475 | - Layering MVs to build a stream pipeline 476 | - How to sink the data out from RisingWave to Clickhouse 477 | 478 | ## What's next? 479 | 480 | https://tutorials.risingwave.com/docs/category/basics 481 | 482 | ## Homework 483 | 484 | To further understand the concepts, please try the [Homework](./homework.md). --------------------------------------------------------------------------------