一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務(wù)器之家:專注于服務(wù)器技術(shù)及軟件下載分享
分類導航

Linux|Centos|Ubuntu|系統(tǒng)進程|Fedora|注冊表|Bios|Solaris|Windows7|Windows10|Windows11|windows server|

服務(wù)器之家 - 服務(wù)器系統(tǒng) - Ubuntu - 在Ubuntu使用SQL?Server創(chuàng)建Go應(yīng)用程序的圖文教程

在Ubuntu使用SQL?Server創(chuàng)建Go應(yīng)用程序的圖文教程

2023-05-09 07:05未知服務(wù)器之家 Ubuntu

目錄 一、設(shè)置環(huán)境 1.1、安裝 SQL Server 1.2、安裝 GoLang 1.3、安裝 ODBC 驅(qū)動程序和 SQL 命令行實用工具 SQL 服務(wù)器 二、使用 SQL 服務(wù)器創(chuàng)建 Go 應(yīng)用程序 2.1、創(chuàng)建連接到 SQL Server 并執(zhí)行查詢的 Go 應(yīng)用 2.2、創(chuàng)建一個使用 GORM 連接到 SQL S

目錄
  • 一、設(shè)置環(huán)境
    • 1.1、安裝 SQL Server
    • 1.2、安裝 GoLang
    • 1.3、安裝 ODBC 驅(qū)動程序和 SQL 命令行實用工具 SQL 服務(wù)器
  • 二、使用 SQL 服務(wù)器創(chuàng)建 Go 應(yīng)用程序
    • 2.1、創(chuàng)建連接到 SQL Server 并執(zhí)行查詢的 Go 應(yīng)用
    • 2.2、創(chuàng)建一個使用 GORM 連接到 SQL Server 的 Go 應(yīng)用程序
  • 三、讓 Go 應(yīng)用的速度提高 100 倍
    • 3.1、使用 sqlcmd 創(chuàng)建一個包含 5 萬個的新表
    • 3.2、創(chuàng)建一個 Go 應(yīng)用程序,用于查詢此表并測量所花費的時間
    • 3.3、測量運行查詢所需的時間
    • 3.4、使用 SQLCMD 向表中添加列存儲索引
    • 3.5、重新運行 columnstore.go 腳本,并注意這次完成查詢所花費的時間
  • 總結(jié)

    一、設(shè)置環(huán)境

    在 Ubuntu 機器上安裝 SQL Server 2017和安裝運行 GoLang 所需的依賴項。

    1.1、安裝 SQL Server

    為了確保 SQL Server 的最佳性能,計算機應(yīng)至少具有 4 GB 的內(nèi)存。

    在Ubuntu使用SQL?Server創(chuàng)建Go應(yīng)用程序的圖文教程

    (2)安裝 SQLCMD 后,可以使用以下命令連接到 SQL Server:

    sqlcmd -S localhost -U sa -P yourpassword
    1> # You're connected! Type your T-SQL statements here. Use the keyword 'GO' to execute each batch of statements.
    

    (3)測試數(shù)據(jù)庫。結(jié)果將打印到標準輸出。

    sqlcmd -S localhost -U sa -P yourpassword -Q "SELECT @@VERSION"
    

    --------------------------------------------------------
    Microsoft SQL Server vNext (CTP2.0) - 14.0.500.272 (X64)
    ?? ?Apr 2 2023 11:44:40
    ?? ?Copyright (c) Microsoft Corporation
    ? ? on Linux (Ubuntu 16.04)

    1 rows(s) returned

    Executed in 1 ns

    至此,已成功在 Ubuntu 機器上安裝 SQL Server 命令行實用程序,已經(jīng)在 Ubuntu 計算機上成功安裝并設(shè)置 GoLang 和 mssql-tools?,F(xiàn)在擁有開始使用 SQL Server 編寫 Go 應(yīng)用程序所需的一切。

    二、使用 SQL 服務(wù)器創(chuàng)建 Go 應(yīng)用程序

    安裝 SQL Server 和 GoLang 后,現(xiàn)在可以繼續(xù)創(chuàng)建新的 Go 項目。在這里,將探討三個簡單的應(yīng)用程序。其中一個將連接并打印數(shù)據(jù)庫服務(wù)器的SQL Server版本,另一個將執(zhí)行基本的插入,更新,刪除和選擇操作,第三個將使用GORM,一種流行的對象關(guān)系映射(ORM)框架,用于Go執(zhí)行相同的操作。

    2.1、創(chuàng)建連接到 SQL Server 并執(zhí)行查詢的 Go 應(yīng)用

    (1)創(chuàng)建新的項目目錄并安裝 Go 依賴項。

    cd ~/
    
    #Create Project Directory
    mkdir SqlServerSample
    cd SqlServerSample
    
    # Get and install the SQL Server driver for Go
    go get github.com/denisenkom/go-mssqldb
    go install github.com/denisenkom/go-mssqldb
    

    (2)通過使用 sqlcmd 連接到 SQL Server 并執(zhí)行以下命令,創(chuàng)建將用于本教程其余部分的數(shù)據(jù)庫。不要忘記使用自己的用戶名和密碼更新用戶名和密碼。

    sqlcmd -S 127.0.0.1 -U sa -P <你的> -Q "CREATE DATABASE SampleDB;"
    

    (3)創(chuàng)建一個連接到 SQL Server 的簡單 Go 應(yīng)用。

    在 SqlServerSample 文件夾中創(chuàng)建一個名為 connect.go 的文件。將以下內(nèi)容復制并粘貼到文件中。不要忘記使用自己的用戶名和密碼更新用戶名和密碼。

    此示例使用 GoLang 上下文方法來確保存在與數(shù)據(jù)庫服務(wù)器的活動連接。

    package main
    
    import (
        _ "github.com/denisenkom/go-mssqldb"
        "database/sql"
        "context"
        "log"
        "fmt"
    )
    
    // Replace with your own connection parameters
    var server = "localhost"
    var port = 1433
    var user = "sa"
    var password = "xxxxxx"
    
    var db *sql.DB
    
    func main() {
        var err error
    
        // Create connection string
        connString := fmt.Sprintf("server=%s;user id=%s;password=%s;port=%d",
            server, user, password, port)
    
        // Create connection pool
        db, err = sql.Open("sqlserver", connString)
        if err != nil {
            log.Fatal("Error creating connection pool: " + err.Error())
        }
        log.Printf("Connected!\n")
    
        // Close the database connection pool after program executes
        defer db.Close()
    
        SelectVersion()
    }
    
    // Gets and prints SQL Server version
    func SelectVersion(){
        // Use background context
        ctx := context.Background()
    
        // Ping database to see if it's still alive.
        // Important for handling network issues and long queries.
        err := db.PingContext(ctx)
        if err != nil {
            log.Fatal("Error pinging database: " + err.Error())
        }
    
        var result string
    
        // Run query and scan for result
        err = db.QueryRowContext(ctx, "SELECT @@version").Scan(&result)
        if err != nil {
            log.Fatal("Scan failed:", err.Error())
        }
        fmt.Printf("%s\n", result)
    }
    

    (4)運行應(yīng)用程序。

    go run connect.go

    執(zhí)行結(jié)果:

    Connected!
    Microsoft SQL Server 2017 (CTP2.1) - 14.0.600.250 (X64)
    ? ? ? ? Apr 2 2017 12:21:23
    ? ? ? ? Copyright (C) 2017 Microsoft Corporation. All rights reserved.
    ? ? ? ? Developer Edition (64-bit) on Linux (Ubuntu 16.04.2 LTS)

    (5)在 SqlServerSample 文件夾中創(chuàng)建一個名為 CreateTestData 的文件.sql。將以下 T-SQL 代碼復制并粘貼到其中。這將創(chuàng)建一個架構(gòu)、表并插入幾行。

    CREATE SCHEMA TestSchema;
    GO
    
    CREATE TABLE TestSchema.Employees (
      Id INT IDENTITY(1,1) NOT NULL PRIMARY KEY,
      Name NVARCHAR(50),
      Location NVARCHAR(50)
    );
    GO
    
    INSERT INTO TestSchema.Employees (Name, Location) VALUES
    (N'Jared', N'Australia'),
    (N'Nikita', N'India'),
    (N'Tom', N'Germany');
    GO
    
    SELECT * FROM TestSchema.Employees;
    GO
    

    (6)使用 sqlcmd 連接到數(shù)據(jù)庫并運行 SQL 腳本以創(chuàng)建架構(gòu)、表并插入一些行。

    sqlcmd -S 127.0.0.1 -U sa -P <你的> -d SampleDB -i ./CreateTestData.sql
    

    執(zhí)行結(jié)果:

    CREATE SCHEMA TestSchema;
    
    Executed in 0 ms
    CREATE TABLE TestSchema.Employees (
      Id INT IDENTITY(1,1) NOT NULL PRIMARY KEY,
      Name NVARCHAR(50),
      Location NVARCHAR(50)
    );
    
    Executed in 0 ms
    INSERT INTO TestSchema.Employees (Name, Location) VALUES
    (N'Jared', N'Australia'),
    (N'Nikita', N'India'),
    (N'Tom', N'Germany');
    
    Executed in 0 ms
    SELECT * FROM TestSchema.Employees;
    Id  Name    Location
    --  ------  ---------
    1   Jared   Australia
    2   Nikita  India
    3   Tom     Germany
    
    3 row(s) returned
    
    Executed in 1 ms
    

    (7)在 SqlServerSample 文件夾中創(chuàng)建一個名為 crud.go 的新文件。將以下代碼復制并粘貼到其中。這將插入、更新、刪除和讀取幾行。

    package main
    
    import (
        _ "github.com/denisenkom/go-mssqldb"
        "database/sql"
        "context"
        "log"
        "fmt"
        "errors"
    )
    
    var db *sql.DB
    
    var server = "localhost"
    var port = 1433
    var user = "sa"
    var password = "你的"
    var database = "SampleDB"
    
    func main() {
        // Build connection string
        connString := fmt.Sprintf("server=%s;user id=%s;password=%s;port=%d;database=%s;",
            server, user, password, port, database)
    
        var err error
    
        // Create connection pool
        db, err = sql.Open("sqlserver", connString)
        if err != nil {
            log.Fatal("Error creating connection pool: ", err.Error())
        }
        ctx := context.Background()
        err = db.PingContext(ctx)
        if err != nil {
            log.Fatal(err.Error())
        }
        fmt.Printf("Connected!\n")
    
        // Create employee
        createID, err := CreateEmployee("Jake", "United States")
        if err != nil {
            log.Fatal("Error creating Employee: ", err.Error())
        }
        fmt.Printf("Inserted ID: %d successfully.\n", createID)
    
        // Read employees
        count, err := ReadEmployees()
        if err != nil {
            log.Fatal("Error reading Employees: ", err.Error())
        }
        fmt.Printf("Read %d row(s) successfully.\n", count)
    
        // Update from database
        updatedRows, err := UpdateEmployee("Jake", "Poland")
        if err != nil {
            log.Fatal("Error updating Employee: ", err.Error())
        }
        fmt.Printf("Updated %d row(s) successfully.\n", updatedRows)
    
        // Delete from database
        deletedRows, err := DeleteEmployee("Jake")
        if err != nil {
            log.Fatal("Error deleting Employee: ", err.Error())
        }
        fmt.Printf("Deleted %d row(s) successfully.\n", deletedRows)
    }
    
    // CreateEmployee inserts an employee record
    func CreateEmployee(name string, location string) (int64, error) {
        ctx := context.Background()
        var err error
    
        if db == nil {
            err = errors.New("CreateEmployee: db is null")
            return -1, err
        }
    
        // Check if database is alive.
        err = db.PingContext(ctx)
        if err != nil {
            return -1, err
        }
    
        tsql := "INSERT INTO TestSchema.Employees (Name, Location) VALUES (@Name, @Location); select convert(bigint, SCOPE_IDENTITY());"
    
        stmt, err := db.Prepare(tsql)
        if err != nil {
            return -1, err
        }
        defer stmt.Close()
    
        row := stmt.QueryRowContext(
            ctx,
            sql.Named("Name", name),
            sql.Named("Location", location))
        var newID int64
        err = row.Scan(&newID)
        if err != nil {
            return -1, err
        }
    
        return newID, nil
    }
    
    // ReadEmployees reads all employee records
    func ReadEmployees() (int, error) {
        ctx := context.Background()
    
        // Check if database is alive.
        err := db.PingContext(ctx)
        if err != nil {
            return -1, err
        }
    
        tsql := fmt.Sprintf("SELECT Id, Name, Location FROM TestSchema.Employees;")
    
        // Execute query
        rows, err := db.QueryContext(ctx, tsql)
        if err != nil {
            return -1, err
        }
    
        defer rows.Close()
    
        var count int
    
        // Iterate through the result set.
        for rows.Next() {
            var name, location string
            var id int
    
            // Get values from row.
            err := rows.Scan(&id, &name, &location)
            if err != nil {
                return -1, err
            }
    
            fmt.Printf("ID: %d, Name: %s, Location: %s\n", id, name, location)
            count++
        }
    
        return count, nil
    }
    
    // UpdateEmployee updates an employee's information
    func UpdateEmployee(name string, location string) (int64, error) {
        ctx := context.Background()
    
        // Check if database is alive.
        err := db.PingContext(ctx)
        if err != nil {
            return -1, err
        }
    
        tsql := fmt.Sprintf("UPDATE TestSchema.Employees SET Location = @Location WHERE Name = @Name")
    
        // Execute non-query with named parameters
        result, err := db.ExecContext(
            ctx,
            tsql,
            sql.Named("Location", location),
            sql.Named("Name", name))
        if err != nil {
            return -1, err
        }
    
        return result.RowsAffected()
    }
    
    // DeleteEmployee deletes an employee from the database
    func DeleteEmployee(name string) (int64, error) {
        ctx := context.Background()
    
        // Check if database is alive.
        err := db.PingContext(ctx)
        if err != nil {
            return -1, err
        }
    
        tsql := fmt.Sprintf("DELETE FROM TestSchema.Employees WHERE Name = @Name;")
    
        // Execute non-query with named parameters
        result, err := db.ExecContext(ctx, tsql, sql.Named("Name", name))
        if err != nil {
            return -1, err
        }
    
        return result.RowsAffected()
    }
    

    (8)運行 crud.go 應(yīng)用以查看結(jié)果。

    go run crud.go

    執(zhí)行結(jié)果:

    Connected!
    Inserted ID: 4 successfully.
    ID: 1, Name: Jared, Location: Australia
    ID: 2, Name: Nikita, Location: India
    ID: 3, Name: Tom, Location: Germany
    ID: 4, Name: Jake, Location: United States
    Read 4 row(s) successfully.
    Updated 1 row(s) successfully.
    Deleted 1 row(s) successfully.

    2.2、創(chuàng)建一個使用 GORM 連接到 SQL Server 的 Go 應(yīng)用程序

    (1)創(chuàng)建應(yīng)用目錄并初始化 Go 依賴項。

    cd ~/
    mkdir SqlServerGormSample
    cd SqlServerGormSample
    
    # Get and install the SQL Server driver for Go
    go get github.com/denisenkom/go-mssqldb
    go install github.com/denisenkom/go-mssqldb
    

    (2)將以下內(nèi)容粘貼到名為orm.go的文件中。確保將密碼變量替換為您自己的變量。

    package main
    
    import (
        "fmt"
        "github.com/jinzhu/gorm"
        _ "github.com/jinzhu/gorm/dialects/mssql"
        "log"
    )
    
    var server = "localhost"
    var port = 1433
    var user = "sa"
    var password = "你的"
    var database = "SampleDB"
    
    // Define a User model struct
    type User struct {
        gorm.Model
        FirstName string
        LastName string
    }
    
    // Define a Task model struct
    type Task struct {
        gorm.Model
        Title string
        DueDate string
        IsComplete bool
        UserID  uint
    }
    
    // Read and print all the tasks
    func ReadAllTasks(db *gorm.DB){
        var users []User
        var tasks []Task
        db.Find(&users)
    
        for _, user := range users{
            db.Model(&user).Related(&tasks)
            fmt.Printf("%s %s's tasks:\n", user.FirstName, user.LastName)
            for _, task := range tasks {
                fmt.Printf("Title: %s\nDueDate: %s\nIsComplete:%t\n\n",
                                task.Title, task.DueDate, task.IsComplete)
            }
        }
    }
    
    // Update a task based on a user
    func UpdateSomeonesTask(db *gorm.DB, userId int){
        var task Task
        db.Where("user_id = ?", userId).First(&task).Update("Title", "Buy donuts for Luis")
        fmt.Printf("Title: %s\nDueDate: %s\nIsComplete:%t\n\n",
                        task.Title, task.DueDate, task.IsComplete)
    }
    
    // Delete all the tasks for a user
    func DeleteSomeonesTasks(db *gorm.DB, userId int){
        db.Where("user_id = ?", userId).Delete(&Task{})
        fmt.Printf("Deleted all tasks for user %d", userId)
    }
    
    func main() {
        connectionString := fmt.Sprintf("server=%s;user id=%s;password=%s;port=%d;database=%s",
                                            server, user, password, port, database)
        db, err := gorm.Open("mssql", connectionString)
    
        if err != nil {
            log.Fatal("Failed to create connection pool. Error: " + err.Error())
        }
        gorm.DefaultCallback.Create().Remove("mssql:set_identity_insert")
        defer db.Close()
    
        fmt.Println("Migrating models...")
        db.AutoMigrate(&User{})
        db.AutoMigrate(&Task{})
    
        // Create awesome Users
        fmt.Println("Creating awesome users...")
        db.Create(&User{FirstName: "Andrea", LastName: "Lam"})      //UserID: 1
        db.Create(&User{FirstName: "Meet", LastName: "Bhagdev"})    //UserID: 2
        db.Create(&User{FirstName: "Luis", LastName: "Bosquez"})    //UserID: 3
    
        // Create appropriate Tasks for each user
        fmt.Println("Creating new appropriate tasks...")
        db.Create(&Task{
            Title: "Do laundry", DueDate: "2017-03-30", IsComplete: false, UserID: 1})
        db.Create(&Task{
            Title: "Mow the lawn", DueDate: "2017-03-30", IsComplete: false, UserID: 2})
        db.Create(&Task{
            Title: "Do more laundry", DueDate: "2017-03-30", IsComplete: false, UserID: 3})
        db.Create(&Task{
            Title: "Watch TV", DueDate: "2017-03-30", IsComplete: false, UserID: 3})
    
        // Read
        fmt.Println("\nReading all the tasks...")
        ReadAllTasks(db)
    
        // Update - update Task title to something more appropriate
        fmt.Println("Updating Andrea's task...")
        UpdateSomeonesTask(db, 1)
    
        // Delete - delete Luis's task
        DeleteSomeonesTasks(db, 3)
    }
    

    (3)運行 orm.go 應(yīng)用。

    go run orm.go

    執(zhí)行結(jié)果:

    [info] removing callback `mssql:set_identity_insert` from C:/Projects/golang-experiments/tutorials/orm.go:70
    Migrating models...
    Creating awesome users...
    Creating new appropriate tasks...

    Reading all the tasks...
    Andrea Lam's tasks:
    Title: Do laundry
    DueDate: 2017-03-30
    IsComplete:false

    Meet Bhagdev's tasks:
    Title: Mow the lawn
    DueDate: 2017-03-30
    IsComplete:false

    Luis Bosquez's tasks:
    Title: Do more laundry
    DueDate: 2017-03-30
    IsComplete:false

    Title: Watch TV
    DueDate: 2017-03-30
    IsComplete:false

    Updating Andrea's task...
    Title: Buy donuts for Luis
    DueDate: 2017-03-30
    IsComplete:false

    Deleted all tasks for user 3

    三、讓 Go 應(yīng)用的速度提高 100 倍

    已了解基礎(chǔ)知識,接下來可以了解如何使用 SQL Server 改進應(yīng)用。通過列存儲索引的簡單示例,以及它們?nèi)绾翁岣邤?shù)據(jù)處理速度。與傳統(tǒng)行存儲索引相比,列存儲索引在分析工作負荷上可實現(xiàn)高達 100 倍的性能,并將數(shù)據(jù)壓縮提高多達 10 倍。

    3.1、使用 sqlcmd 創(chuàng)建一個包含 5 萬個的新表

    (1)切換到主目錄并為項目創(chuàng)建一個文件夾。

    cd ~/mkdir SqlServerColumnstoreSamplecd SqlServerColumnstoreSample

    (2)在 SqlServerColumnstoreSample 文件夾中創(chuàng)建一個名為 CreateSampleTable 的新文件.sql文件。將下面的 T-SQL 代碼粘貼到新的 SQL 文件中。保存并關(guān)閉文件。

    WITH a AS (SELECT * FROM (VALUES(1),(2),(3),(4),(5),(6),(7),(8),(9),(10)) AS a(a))
    SELECT TOP(5000000)
    ROW_NUMBER() OVER (ORDER BY a.a) AS OrderItemId
    ,a.a + b.a + c.a + d.a + e.a + f.a + g.a + h.a AS OrderId
    ,a.a * 10 AS Price
    ,CONCAT(a.a, N' ', b.a, N' ', c.a, N' ', d.a, N' ', e.a, N' ', f.a, N' ', g.a, N' ', h.a) AS ProductName
    INTO Table_with_5M_rows
    FROM a, a AS b, a AS c, a AS d, a AS e, a AS f, a AS g, a AS h;
    

    (3)使用 sqlcmd 連接到數(shù)據(jù)庫并運行 SQL 腳本以創(chuàng)建包含 5 萬行的表。這可能需要幾分鐘才能運行。

    sqlcmd -S 127.0.0.1 -U sa -P <你的> -d SampleDB -i ./CreateSampleTable.sql
    

    3.2、創(chuàng)建一個 Go 應(yīng)用程序,用于查詢此表并測量所花費的時間

    (1)在項目文件夾中,初始化 Go 依賴項。

    go get github.com/denisenkom/go-mssqldb
    go install github.com/denisenkom/go-mssqldb
    

    (2)在您的文件夾中創(chuàng)建一個名為 columnstore.go 的文件。

    package main
    
    import (
        _ "github.com/denisenkom/go-mssqldb"
        "database/sql"
        "context"
        "log"
        "fmt"
        "time"
    )
    
    var server = "localhost"
    var port = 1433
    var user = "sa"
    var password = "你的"
    var database = "SampleDB"
    
    var db *sql.DB
    
    // Delete an employee from database
    func ExecuteAggregateStatement(db *sql.DB) {
        ctx := context.Background()
    
        // Ping database to see if it's still alive.
        // Important for handling network issues and long queries.
        err := db.PingContext(ctx)
        if err != nil {
            log.Fatal("Error pinging database: " + err.Error())
        }
    
        var result string
    
        // Execute long non-query to aggregate rows
        err = db.QueryRowContext(ctx, "SELECT SUM(Price) as sum FROM Table_with_5M_rows").Scan(&result)
        if err != nil {
            log.Fatal("Error executing query: " + err.Error())
        }
    
        fmt.Printf("Sum: %s\n", result)
    }
    
    func main() {
        // Connect to database
        connString := fmt.Sprintf("server=%s;user id=%s;password=%s;port=%d;database=%s;",
                                    server, user, password, port, database)
        var err error
    
        // Create connection pool
        db, err = sql.Open("sqlserver", connString)
        if err != nil {
            log.Fatal("Open connection failed:", err.Error())
        }
        fmt.Printf("Connected!\n")
    
        defer db.Close()
    
        t1 := time.Now()
        fmt.Printf("Start time: %s\n", t1)
    
        ExecuteAggregateStatement(db)
    
        t2 := time.Since(t1)
        fmt.Printf("The query took: %s\n", t2)
    }
    

    3.3、測量運行查詢所需的時間

    從終端運行 Go 應(yīng)用。

    go run columnstore.go
    

    執(zhí)行結(jié)果:

    Connected!
    Start time: 2023-04-02 15:33:50.0340976 -0700 PDT
    Sum: 50000000
    The query took: 601.7463ms

    3.4、使用 SQLCMD 向表中添加列存儲索引

    運行以下命令以在表上創(chuàng)建列存儲索引:

    sqlcmd -S localhost -U sa -P <你的> -d SampleDB -Q "CREATE CLUSTERED COLUMNSTORE INDEX Columnstoreindex ON Table_with_5M_rows;"
    

    3.5、重新運行 columnstore.go 腳本,并注意這次完成查詢所花費的時間

    go run columnstore.go
    

    Connected!
    Start time: 2017-06-05 16:35:02.5409285 -0700 PDT
    Sum: 50000000
    The query took: 86.9826ms

    總結(jié)

    使用列存儲索引使 Go 應(yīng)用更快。

    參考文檔。

    原文地址:http://www.ythuaji.com.cn/uploads/allimg/xkijul50cys

    延伸 · 閱讀

    精彩推薦
    主站蜘蛛池模板: 国产精品激情综合久久 | 香蕉eeww99国产精选播放 | 亚洲免费高清视频 | 日本一区二区在线不卡 | 特黄特色大片免费高清视频 | 亚洲国产精品免费在线观看 | 国产高清免费在线 | 欧美日韩一区二区三区韩大 | 91香蕉国产在线观看人员 | 日产精品一卡2卡三卡4乱码久久 | 男模chinesegayxxxx| 成人观看免费大片在线观看 | 大伊香蕉精品二区视频在线 | 亚洲狠狠婷婷综合久久蜜桃 | 俄罗斯性高清完整版 | 情人梁家辉在线 | 青草国产| 国产欧美久久久精品影院 | 亚洲日韩精品欧美一区二区 | x8x8在线永久免费观看 | 范冰冰上面好大下面好紧 | 男人女人性生活视频 | 国产成人影院在线观看 | 亚洲四虎影院 | 色天天综合色天天看 | 婷婷网址 | a看片| 九九九九在线精品免费视频 | 被肉日常np高h | 女教师的一级毛片 | 久久re视频精品538在线 | 午夜在线观看免费完整直播网 | 日韩一区国产二区欧美三 | 欧美成人福利 | 欧美色青 | 91天堂素人97年清纯嫩模 | 日本阿v在线播放 | 久久精品AV一区二区无码 | 忘忧草在线社区WWW日本-韩国 | 欧美人交性视频在线香蕉 | 91美女在线 |